From 6118a5e76a070dce09a2ac8a6d22175a25c098e7 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Thu, 16 Jan 2025 18:53:42 +0000 Subject: [PATCH 1/2] Optimize bytecode size of mirror --- src/DN404Mirror.sol | 87 +++++++++++++++++------------------------- test/DN404Mirror.t.sol | 51 ++++++++++++++++++++----- 2 files changed, 75 insertions(+), 63 deletions(-) diff --git a/src/DN404Mirror.sol b/src/DN404Mirror.sol index 7a204ba..8f196e8 100644 --- a/src/DN404Mirror.sol +++ b/src/DN404Mirror.sol @@ -280,8 +280,12 @@ contract DN404Mirror { /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`. function safeTransferFrom(address from, address to, uint256 id) public payable virtual { - transferFrom(from, to, id); - if (_hasCode(to)) _checkOnERC721Received(from, to, id, ""); + bytes calldata emptyData; + /// @solidity memory-safe-assembly + assembly { + emptyData.length := 0 + } + safeTransferFrom(from, to, id, emptyData); } /// @dev Transfers token `id` from `from` to `to`. @@ -302,7 +306,34 @@ contract DN404Mirror { virtual { transferFrom(from, to, id); - if (_hasCode(to)) _checkOnERC721Received(from, to, id, data); + /// @solidity memory-safe-assembly + assembly { + if extcodesize(to) { + // Prepare the calldata. + let m := mload(0x40) + let onERC721ReceivedSelector := 0x150b7a02 + mstore(m, onERC721ReceivedSelector) + mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`. + mstore(add(m, 0x40), shr(96, shl(96, from))) + mstore(add(m, 0x60), id) + mstore(add(m, 0x80), 0x80) + mstore(add(m, 0xa0), data.length) + calldatacopy(add(m, 0xc0), data.offset, data.length) + // Revert if the call reverts. + if iszero(call(gas(), to, 0, add(m, 0x1c), add(data.length, 0xa4), m, 0x20)) { + if returndatasize() { + // Bubble up the revert if the call reverts. + returndatacopy(m, 0x00, returndatasize()) + revert(m, returndatasize()) + } + } + // Load the returndata and compare it. + if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) { + mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`. + revert(0x1c, 0x04) + } + } + } } /// @dev Returns true if this contract implements the interface defined by `interfaceId`. @@ -498,14 +529,6 @@ contract DN404Mirror { } } - /// @dev Returns if `a` has bytecode of non-zero length. - function _hasCode(address a) private view returns (bool result) { - /// @solidity memory-safe-assembly - assembly { - result := extcodesize(a) // Can handle dirty upper bits. - } - } - /// @dev More bytecode-efficient way to revert. function _rv(uint32 s) private pure { /// @solidity memory-safe-assembly @@ -514,46 +537,4 @@ contract DN404Mirror { revert(0x1c, 0x04) } } - - /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`. - /// Reverts if the target does not support the function correctly. - function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data) - private - { - /// @solidity memory-safe-assembly - assembly { - // Prepare the calldata. - let m := mload(0x40) - let onERC721ReceivedSelector := 0x150b7a02 - mstore(m, onERC721ReceivedSelector) - mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`. - mstore(add(m, 0x40), shr(96, shl(96, from))) - mstore(add(m, 0x60), id) - mstore(add(m, 0x80), 0x80) - let n := mload(data) - mstore(add(m, 0xa0), n) - if n { - let dst := add(m, 0xc0) - let end := add(dst, n) - for { let d := sub(add(data, 0x20), dst) } 1 {} { - mstore(dst, mload(add(dst, d))) - dst := add(dst, 0x20) - if iszero(lt(dst, end)) { break } - } - } - // Revert if the call reverts. - if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) { - if returndatasize() { - // Bubble up the revert if the call reverts. - returndatacopy(m, 0x00, returndatasize()) - revert(m, returndatasize()) - } - } - // Load the returndata and compare it. - if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) { - mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`. - revert(0x1c, 0x04) - } - } - } } diff --git a/test/DN404Mirror.t.sol b/test/DN404Mirror.t.sol index 86a5b08..229ea7e 100644 --- a/test/DN404Mirror.t.sol +++ b/test/DN404Mirror.t.sol @@ -7,7 +7,19 @@ import {MockDN404Ownable} from "./utils/mocks/MockDN404Ownable.sol"; import {DN404Mirror, MockDN404Mirror} from "./utils/mocks/MockDN404Mirror.sol"; import {LibSort} from "solady/utils/LibSort.sol"; -contract Invalid721Receiver {} +contract InvalidERC721Receiver {} + +contract ERC721Receiver { + bytes32 public lastReceivedHash; + + function onERC721Received(address by, address from, uint256 id, bytes calldata data) + public + returns (bytes4) + { + lastReceivedHash = keccak256(abi.encode(by, from, id, keccak256(data))); + return msg.sig; + } +} contract DN404MirrorTest is SoladyTest { event Transfer(address indexed from, address indexed to, uint256 indexed id); @@ -206,25 +218,44 @@ contract DN404MirrorTest is SoladyTest { } } - function testSafeTransferFrom(uint32 totalNFTSupply) public { + function testSafeTransferFrom(uint32 totalNFTSupply, bytes memory randomBytes) public { totalNFTSupply = uint32(_bound(totalNFTSupply, 5, 1000000)); address alice = address(111); address bob = address(222); - address invalid = address(new Invalid721Receiver()); dn.initializeDN404(uint96(uint256(totalNFTSupply) * _WAD), address(this), address(mirror)); dn.transfer(alice, _WAD * uint256(5)); assertEq(mirror.balanceOf(alice), 5); assertEq(mirror.balanceOf(bob), 0); - vm.prank(alice); - vm.expectRevert(DN404Mirror.TransferToNonERC721ReceiverImplementer.selector); - mirror.safeTransferFrom(alice, invalid, 1); + if (_random() % 2 == 0) { + address to = address(new InvalidERC721Receiver()); + + vm.prank(alice); + vm.expectRevert(DN404Mirror.TransferToNonERC721ReceiverImplementer.selector); + mirror.safeTransferFrom(alice, to, 1); + + vm.prank(alice); + mirror.safeTransferFrom(alice, bob, 1); + assertEq(mirror.balanceOf(alice), 4); + assertEq(mirror.balanceOf(bob), 1); + } else { + address to = address(new ERC721Receiver()); + address operator = _randomNonZeroAddress(); + vm.prank(alice); + mirror.setApprovalForAll(operator, true); + + if (randomBytes.length == 0 && _random() % 2 == 0) { + vm.prank(operator); + mirror.safeTransferFrom(alice, to, 1); + } else { + vm.prank(operator); + mirror.safeTransferFrom(alice, to, 1, randomBytes); + } - vm.prank(alice); - mirror.safeTransferFrom(alice, bob, 1); - assertEq(mirror.balanceOf(alice), 4); - assertEq(mirror.balanceOf(bob), 1); + bytes32 h = keccak256(abi.encode(operator, alice, 1, keccak256(randomBytes))); + assertEq(ERC721Receiver(to).lastReceivedHash(), h); + } } function testLinkMirrorContract() public { From fea7011f725da791f4eb1b9dc55ed5fbe80c2628 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Thu, 16 Jan 2025 18:54:48 +0000 Subject: [PATCH 2/2] T --- .gas-snapshot | 94 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 6082148..2d2a678 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -67,19 +67,19 @@ BenchTest:testMintDN420_13() (gas: 111184) BenchTest:testMintDN420_14() (gas: 112569) BenchTest:testMintDN420_15() (gas: 114041) BenchTest:testMintDN420_16() (gas: 115447) -BenchTest:test__codesize() (gas: 28252) +BenchTest:test__codesize() (gas: 28114) DN404CustomUnitTest:testInitializeCorrectUnitSuccess() (gas: 130120) DN404CustomUnitTest:testInitializeWithUnitTooLargeReverts() (gas: 33791) DN404CustomUnitTest:testInitializeWithZeroUnitReverts() (gas: 13864) DN404CustomUnitTest:testMint() (gas: 163237) -DN404CustomUnitTest:testMintWithoutNFTs(uint256,uint256,uint256) (runs: 276, μ: 160409, ~: 162733) +DN404CustomUnitTest:testMintWithoutNFTs(uint256,uint256,uint256) (runs: 276, μ: 160424, ~: 162733) DN404CustomUnitTest:testNFTMint() (gas: 64873666) -DN404CustomUnitTest:testNFTMintAndBurn(uint256,uint256,uint256) (runs: 276, μ: 207856, ~: 159094) -DN404CustomUnitTest:testNFTMintViaTransfer(uint256,uint256,uint256) (runs: 276, μ: 235488, ~: 250925) -DN404CustomUnitTest:testTotalSupplyOverflowsTrick(uint256,uint256) (runs: 276, μ: 604, ~: 664) -DN404CustomUnitTest:testTotalSupplyOverflowsTrick(uint256,uint256,uint256) (runs: 276, μ: 775, ~: 746) +DN404CustomUnitTest:testNFTMintAndBurn(uint256,uint256,uint256) (runs: 276, μ: 203500, ~: 159083) +DN404CustomUnitTest:testNFTMintViaTransfer(uint256,uint256,uint256) (runs: 276, μ: 232805, ~: 250925) +DN404CustomUnitTest:testTotalSupplyOverflowsTrick(uint256,uint256) (runs: 276, μ: 603, ~: 664) +DN404CustomUnitTest:testTotalSupplyOverflowsTrick(uint256,uint256,uint256) (runs: 276, μ: 776, ~: 746) DN404CustomUnitTest:testUnitInvalidCheckTrick(uint256) (runs: 276, μ: 526, ~: 527) -DN404CustomUnitTest:test__codesize() (gas: 28781) +DN404CustomUnitTest:test__codesize() (gas: 28643) DN404MirrorTest:testAutomaticPullOwnerWithOwnable() (gas: 3664602) DN404MirrorTest:testAutomaticPullOwnerWithOwnable2() (gas: 3652679) DN404MirrorTest:testBaseERC20() (gas: 114787) @@ -87,53 +87,53 @@ DN404MirrorTest:testFnSelectorNotRecognized() (gas: 6247) DN404MirrorTest:testLinkMirrorContract() (gas: 39410) DN404MirrorTest:testLogDirectTransfers() (gas: 395961) DN404MirrorTest:testLogTransfer() (gas: 120943) -DN404MirrorTest:testNameAndSymbol(string,string) (runs: 276, μ: 203765, ~: 207074) +DN404MirrorTest:testNameAndSymbol(string,string) (runs: 276, μ: 203835, ~: 207144) DN404MirrorTest:testNotLinked() (gas: 12794) DN404MirrorTest:testPullOwner() (gas: 112833) -DN404MirrorTest:testSafeTransferFrom(uint32) (runs: 276, μ: 478719, ~: 478658) +DN404MirrorTest:testSafeTransferFrom(uint32,bytes) (runs: 276, μ: 533926, ~: 502002) DN404MirrorTest:testSetAndGetApprovalForAll() (gas: 331059) DN404MirrorTest:testSetAndGetApproved() (gas: 328139) -DN404MirrorTest:testSupportsInterface() (gas: 7567) -DN404MirrorTest:testTokenURI(string,uint256) (runs: 276, μ: 261507, ~: 266260) -DN404MirrorTest:testTransferFrom(uint32) (runs: 276, μ: 379939, ~: 379878) -DN404MirrorTest:testTransferFromMixed(uint256) (runs: 276, μ: 785229, ~: 716434) -DN404MirrorTest:test__codesize() (gas: 60249) +DN404MirrorTest:testSupportsInterface() (gas: 7544) +DN404MirrorTest:testTokenURI(string,uint256) (runs: 276, μ: 261981, ~: 266295) +DN404MirrorTest:testTransferFrom(uint32) (runs: 276, μ: 379975, ~: 379913) +DN404MirrorTest:testTransferFromMixed(uint256) (runs: 276, μ: 765680, ~: 687875) +DN404MirrorTest:test__codesize() (gas: 61980) DN404OnlyERC20Test:testApprove() (gas: 35902) DN404OnlyERC20Test:testApprove(address,uint256) (runs: 276, μ: 31380, ~: 31453) DN404OnlyERC20Test:testBurn() (gas: 48166) -DN404OnlyERC20Test:testBurn(address,uint256,uint256) (runs: 276, μ: 49031, ~: 49345) -DN404OnlyERC20Test:testBurnInsufficientBalanceReverts(address,uint256,uint256) (runs: 276, μ: 42229, ~: 42379) +DN404OnlyERC20Test:testBurn(address,uint256,uint256) (runs: 276, μ: 49020, ~: 49345) +DN404OnlyERC20Test:testBurnInsufficientBalanceReverts(address,uint256,uint256) (runs: 276, μ: 42238, ~: 42379) DN404OnlyERC20Test:testInfiniteApproveTransferFrom() (gas: 82978) DN404OnlyERC20Test:testMaxSupplyTrick(uint256) (runs: 276, μ: 541, ~: 541) DN404OnlyERC20Test:testMetadata() (gas: 8962) DN404OnlyERC20Test:testMint() (gas: 44065) DN404OnlyERC20Test:testMintOverMaxLimitReverts() (gas: 42035) -DN404OnlyERC20Test:testMintz(address,uint256) (runs: 276, μ: 44725, ~: 44487) +DN404OnlyERC20Test:testMintz(address,uint256) (runs: 276, μ: 44640, ~: 44487) DN404OnlyERC20Test:testTransfer() (gas: 58082) -DN404OnlyERC20Test:testTransfer(address,uint256) (runs: 276, μ: 58729, ~: 58491) +DN404OnlyERC20Test:testTransfer(address,uint256) (runs: 276, μ: 58644, ~: 58491) DN404OnlyERC20Test:testTransferFrom() (gas: 79976) -DN404OnlyERC20Test:testTransferFrom(address,address,address,uint256,uint256) (runs: 276, μ: 87059, ~: 88405) +DN404OnlyERC20Test:testTransferFrom(address,address,address,uint256,uint256) (runs: 276, μ: 87062, ~: 88405) DN404OnlyERC20Test:testTransferFromInsufficientAllowanceReverts() (gas: 66880) -DN404OnlyERC20Test:testTransferFromInsufficientAllowanceReverts(address,uint256,uint256) (runs: 276, μ: 67849, ~: 67959) +DN404OnlyERC20Test:testTransferFromInsufficientAllowanceReverts(address,uint256,uint256) (runs: 276, μ: 67858, ~: 67959) DN404OnlyERC20Test:testTransferFromInsufficientBalanceReverts() (gas: 51747) -DN404OnlyERC20Test:testTransferFromInsufficientBalanceReverts(address,uint256,uint256) (runs: 276, μ: 52378, ~: 52524) +DN404OnlyERC20Test:testTransferFromInsufficientBalanceReverts(address,uint256,uint256) (runs: 276, μ: 52385, ~: 52534) DN404OnlyERC20Test:testTransferInsufficientBalanceReverts() (gas: 43948) -DN404OnlyERC20Test:testTransferInsufficientBalanceReverts(address,uint256,uint256) (runs: 276, μ: 44927, ~: 45057) -DN404OnlyERC20Test:test__codesize() (gas: 28201) +DN404OnlyERC20Test:testTransferInsufficientBalanceReverts(address,uint256,uint256) (runs: 276, μ: 44936, ~: 45057) +DN404OnlyERC20Test:test__codesize() (gas: 28063) DN404Test:testBatchNFTLog() (gas: 327308) DN404Test:testBurnOnTransfer(uint32,address) (runs: 274, μ: 275863, ~: 275863) DN404Test:testFnSelectorNotRecognized() (gas: 6256) -DN404Test:testInitialize(uint32,address) (runs: 276, μ: 112730, ~: 113808) +DN404Test:testInitialize(uint32,address) (runs: 276, μ: 112465, ~: 113808) DN404Test:testMintAndBurn() (gas: 346843) DN404Test:testMintAndBurn2() (gas: 283400) DN404Test:testMintNext() (gas: 707821) -DN404Test:testMintNextContiguous(uint256) (runs: 276, μ: 588301, ~: 538017) +DN404Test:testMintNextContiguous(uint256) (runs: 276, μ: 580234, ~: 530149) DN404Test:testMintOnTransfer(uint32,address) (runs: 274, μ: 290438, ~: 290438) -DN404Test:testMixed(bytes32) (runs: 276, μ: 530506, ~: 477345) +DN404Test:testMixed(bytes32) (runs: 276, μ: 535439, ~: 477565) DN404Test:testNameAndSymbol(string,string) (runs: 276, μ: 203567, ~: 206876) DN404Test:testNumAliasesOverflowReverts() (gas: 40944) DN404Test:testOwnedIds() (gas: 361141) -DN404Test:testOwnedIds(uint256) (runs: 276, μ: 268325, ~: 284584) +DN404Test:testOwnedIds(uint256) (runs: 276, μ: 270712, ~: 285417) DN404Test:testPermit2() (gas: 456313) DN404Test:testRegisterAndResolveAlias(address,address) (runs: 276, μ: 120191, ~: 120191) DN404Test:testSetAndGetAux(address,uint88) (runs: 276, μ: 22056, ~: 22274) @@ -142,33 +142,33 @@ DN404Test:testSetAndGetSkipNFT() (gas: 708368) DN404Test:testTokenURI(string,uint256) (runs: 276, μ: 12997903, ~: 12975480) DN404Test:testTransferWithMirrorEvent() (gas: 411009) DN404Test:testTransfersAndBurns() (gas: 488426) -DN404Test:testWrapAround(uint32,uint256) (runs: 276, μ: 392580, ~: 389199) -DN404Test:test__codesize() (gas: 61066) +DN404Test:testWrapAround(uint32,uint256) (runs: 276, μ: 392860, ~: 389199) +DN404Test:test__codesize() (gas: 60928) DN404ZeroIndexedTest:testBatchNFTLog() (gas: 326747) -DN404ZeroIndexedTest:testBurnOnTransfer(uint32,address) (runs: 274, μ: 255773, ~: 255783) +DN404ZeroIndexedTest:testBurnOnTransfer(uint32,address) (runs: 274, μ: 255783, ~: 255783) DN404ZeroIndexedTest:testFnSelectorNotRecognized() (gas: 6256) -DN404ZeroIndexedTest:testInitialize(uint32,address) (runs: 276, μ: 111139, ~: 113802) +DN404ZeroIndexedTest:testInitialize(uint32,address) (runs: 276, μ: 111178, ~: 113802) DN404ZeroIndexedTest:testMintAndBurn() (gas: 343724) DN404ZeroIndexedTest:testMintAndBurn2() (gas: 280984) DN404ZeroIndexedTest:testMintNext() (gas: 704822) -DN404ZeroIndexedTest:testMintNextContiguous(uint256) (runs: 276, μ: 574967, ~: 529585) -DN404ZeroIndexedTest:testMintOnTransfer(uint32,address) (runs: 274, μ: 270394, ~: 270404) -DN404ZeroIndexedTest:testMixed(bytes32) (runs: 276, μ: 517435, ~: 451049) +DN404ZeroIndexedTest:testMintNextContiguous(uint256) (runs: 276, μ: 573892, ~: 527005) +DN404ZeroIndexedTest:testMintOnTransfer(uint32,address) (runs: 274, μ: 270404, ~: 270404) +DN404ZeroIndexedTest:testMixed(bytes32) (runs: 276, μ: 541159, ~: 483085) DN404ZeroIndexedTest:testNameAndSymbol(string,string) (runs: 276, μ: 203516, ~: 206825) DN404ZeroIndexedTest:testNumAliasesOverflowReverts() (gas: 40944) DN404ZeroIndexedTest:testOwnedIds() (gas: 348030) -DN404ZeroIndexedTest:testOwnedIds(uint256) (runs: 276, μ: 268702, ~: 285180) +DN404ZeroIndexedTest:testOwnedIds(uint256) (runs: 276, μ: 270873, ~: 287994) DN404ZeroIndexedTest:testPermit2() (gas: 455948) DN404ZeroIndexedTest:testRegisterAndResolveAlias(address,address) (runs: 276, μ: 120118, ~: 120191) -DN404ZeroIndexedTest:testSetAndGetAux(address,uint88) (runs: 276, μ: 22074, ~: 22290) +DN404ZeroIndexedTest:testSetAndGetAux(address,uint88) (runs: 276, μ: 22074, ~: 22292) DN404ZeroIndexedTest:testSetAndGetOperatorApprovals(address,address,bool) (runs: 276, μ: 130339, ~: 120534) DN404ZeroIndexedTest:testSetAndGetSkipNFT() (gas: 708390) DN404ZeroIndexedTest:testTokenURI(string,uint256) (runs: 276, μ: 157093, ~: 134670) DN404ZeroIndexedTest:testTransferWithMirrorEvent() (gas: 410515) DN404ZeroIndexedTest:testTransfersAndBurns() (gas: 486461) -DN404ZeroIndexedTest:testWrapAround(uint32,uint256) (runs: 276, μ: 378032, ~: 383784) -DN404ZeroIndexedTest:testWrapNFTIdEquivalence(uint256,uint256,bool) (runs: 276, μ: 1379, ~: 1418) -DN404ZeroIndexedTest:test__codesize() (gas: 60861) +DN404ZeroIndexedTest:testWrapAround(uint32,uint256) (runs: 276, μ: 376766, ~: 383784) +DN404ZeroIndexedTest:testWrapNFTIdEquivalence(uint256,uint256,bool) (runs: 276, μ: 1382, ~: 1440) +DN404ZeroIndexedTest:test__codesize() (gas: 60723) DN420OnlyERC20Test:testApprove() (gas: 35869) DN420OnlyERC20Test:testApprove(address,uint256) (runs: 276, μ: 31347, ~: 31420) DN420OnlyERC20Test:testBurn() (gas: 49038) @@ -223,16 +223,16 @@ MaxUnitInvariant:invariantMirrorAndBaseRemainImmutable() (runs: 10, calls: 150, MaxUnitInvariant:invariantNoUserOwnsInvalidToken() (runs: 10, calls: 150, reverts: 0) MaxUnitInvariant:invariantTotalReflectionIsValid() (runs: 10, calls: 150, reverts: 0) MaxUnitInvariant:invariantUserReflectionIsValid() (runs: 10, calls: 150, reverts: 0) -MintTests:test_WhenAmountIsGreaterThan_MAX_SUPPLYOrMintMakesNFTTotalSupplyExceed_MAX_SUPPLY(uint256) (runs: 276, μ: 60470, ~: 61591) -MintTests:test_WhenRecipientAddressHasSkipNFTEnabled(uint256) (runs: 276, μ: 85931, ~: 85934) -MintTests:test_WhenRecipientIsAddress0(uint256) (runs: 276, μ: 31043, ~: 30966) -MintTests:test_WhenRecipientsBalanceDifferenceIsNotUpTo1e18(uint256) (runs: 276, μ: 82999, ~: 83101) -MintTests:test_WhenRecipientsBalanceDifferenceIsUpTo1e18OrAbove(uint256) (runs: 276, μ: 89519, ~: 89631) -MintTests:test__codesize() (gas: 27378) +MintTests:test_WhenAmountIsGreaterThan_MAX_SUPPLYOrMintMakesNFTTotalSupplyExceed_MAX_SUPPLY(uint256) (runs: 276, μ: 60713, ~: 61594) +MintTests:test_WhenRecipientAddressHasSkipNFTEnabled(uint256) (runs: 276, μ: 85951, ~: 85935) +MintTests:test_WhenRecipientIsAddress0(uint256) (runs: 276, μ: 31047, ~: 30966) +MintTests:test_WhenRecipientsBalanceDifferenceIsNotUpTo1e18(uint256) (runs: 276, μ: 82981, ~: 83100) +MintTests:test_WhenRecipientsBalanceDifferenceIsUpTo1e18OrAbove(uint256) (runs: 276, μ: 89511, ~: 89631) +MintTests:test__codesize() (gas: 27240) NFTMintDN404Test:testAllowlistMint() (gas: 258872) NFTMintDN404Test:testMint() (gas: 231574) NFTMintDN404Test:testTotalSupplyReached() (gas: 628086918) -NFTMintDN404Test:test__codesize() (gas: 22437) +NFTMintDN404Test:test__codesize() (gas: 22299) NonMultipleUnitInvariant:invariantBurnedPoolLengthIsTailMinusHead() (runs: 10, calls: 150, reverts: 0) NonMultipleUnitInvariant:invariantDN404BalanceSum() (runs: 10, calls: 150, reverts: 0) NonMultipleUnitInvariant:invariantMirror721BalanceSum() (runs: 10, calls: 150, reverts: 0) @@ -244,7 +244,7 @@ SimpleDN404Test:testMint() (gas: 49579) SimpleDN404Test:testName() (gas: 9134) SimpleDN404Test:testSymbol() (gas: 9132) SimpleDN404Test:testWithdraw() (gas: 20732) -SimpleDN404Test:test__codesize() (gas: 18359) +SimpleDN404Test:test__codesize() (gas: 18221) SoladyTest:test__codesize() (gas: 840) TestPlus:test__codesize() (gas: 406) WADUnitInvariant:invariantBurnedPoolLengthIsTailMinusHead() (runs: 10, calls: 150, reverts: 0)