diff --git a/.gas-snapshot b/.gas-snapshot index 36583e0..6d1eb9d 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,233 +1,269 @@ -ClawbackMetadataTest:testDurationAndUnlocksAt() (gas: 500605) -ClawbackMetadataTest:testMetadataPropertiesERC1155((uint8,uint32,uint56,uint256),(bool,bool,uint56,address)) (runs: 1028, μ: 157404, ~: 146685) -ClawbackMetadataTest:testMetadataPropertiesERC20((uint8,uint32,uint56,uint256),(bool,bool,uint56,address)) (runs: 1028, μ: 160087, ~: 160057) -ClawbackMetadataTest:testMetadataPropertiesERC721((uint8,uint32,uint56,uint256),(bool,bool,uint56,address)) (runs: 1028, μ: 258233, ~: 254559) -ClawbackMetadataTest:testSupportsInterface() (gas: 9612) -ClawbackTest:testAddTemplate(address,uint56,bool,bool) (runs: 1028, μ: 46910, ~: 46910) -ClawbackTest:testAddTemplateTransferer(address,address) (runs: 1028, μ: 77227, ~: 77227) -ClawbackTest:testAddTemplateTransfererInvalidCaller(address,address,bool,address) (runs: 1028, μ: 62874, ~: 75750) -ClawbackTest:testAddToWrap(address,uint8,uint256,uint256,uint56,address,uint64) (runs: 1024, μ: 285447, ~: 260570) -ClawbackTest:testAddToWrapInvalidWrappedId(uint256,uint256,address) (runs: 1028, μ: 13962, ~: 13962) -ClawbackTest:testClawback(uint8,uint256,uint256,uint56,address,address) (runs: 1028, μ: 278594, ~: 300635) -ClawbackTest:testClawbackAfterTransfer(uint8,uint256,uint256,uint56,address,address,address) (runs: 1028, μ: 305487, ~: 324613) -ClawbackTest:testClawbackDestructionOnly(uint8,uint256,uint256,uint56,address) (runs: 1028, μ: 279812, ~: 305452) -ClawbackTest:testClawbackDestructionOnlyInvalidReceiver(uint8,uint256,uint256,uint56,address,address) (runs: 1028, μ: 268228, ~: 292765) -ClawbackTest:testClawbackInvalidCaller(uint8,uint256,uint256,uint56,address,address) (runs: 1028, μ: 234653, ~: 259070) -ClawbackTest:testClawbackInvalidUnlocked(uint8,uint256,uint256,uint56,address,address) (runs: 1028, μ: 262031, ~: 286568) -ClawbackTest:testEmergencyClawback(uint8,uint256,uint256,uint56,address,address) (runs: 1028, μ: 290457, ~: 317524) -ClawbackTest:testEmergencyClawbackAfterTransfer(uint8,uint256,uint256,uint56,address,address,address) (runs: 1028, μ: 313406, ~: 340998) -ClawbackTest:testEmergencyClawbackDestructionOnly(uint8,uint256,uint256,uint56,address) (runs: 1028, μ: 290443, ~: 321459) -ClawbackTest:testEmergencyClawbackDestructionOnlyInvalidReceiver(uint8,uint256,uint256,uint56,address,address) (runs: 1028, μ: 268748, ~: 293285) -ClawbackTest:testEmergencyClawbackInvalidCaller(uint8,uint256,uint256,uint56,address,address) (runs: 1028, μ: 233699, ~: 258116) -ClawbackTest:testEmergencyClawbackInvalidUnlocked(uint8,uint256,uint256,uint56,address,address) (runs: 1028, μ: 262441, ~: 286978) -ClawbackTest:testPreventsOnERC1155Received(uint256,uint256) (runs: 1028, μ: 100436, ~: 100354) -ClawbackTest:testPreventsOnERC1155Received(uint256,uint256,uint256,uint256) (runs: 1028, μ: 159374, ~: 159370) -ClawbackTest:testPreventsOnERC721Received(uint256) (runs: 1028, μ: 118375, ~: 118374) -ClawbackTest:testSupportsInterface() (gas: 13448) -ClawbackTest:testTransferByTransfererAsFrom(uint8,uint256,uint256,uint56,uint64,bool,address,bool) (runs: 1028, μ: 276943, ~: 300766) -ClawbackTest:testTransferByTransfererAsOperator(uint8,uint256,uint256,uint56,uint64,bool,address,address,bool) (runs: 1028, μ: 301157, ~: 326941) -ClawbackTest:testTransferByTransfererAsTo(uint8,uint256,uint256,uint56,uint64,bool,address,bool) (runs: 1028, μ: 277516, ~: 301339) -ClawbackTest:testTransferByTransfererNotApproved(uint8,uint256,uint256,uint56,uint64,bool,address,address,bool) (runs: 1028, μ: 267919, ~: 294638) -ClawbackTest:testTransferInvalidOperator(uint8,uint256,uint256,uint56,address,address,bool) (runs: 1028, μ: 269212, ~: 294463) -ClawbackTest:testTransferOpen(uint8,uint256,uint256,uint56,uint64,address) (runs: 1028, μ: 249918, ~: 275183) -ClawbackTest:testUnwrap(address,uint8,uint256,uint256,uint56,uint64) (runs: 1028, μ: 238260, ~: 243165) -ClawbackTest:testUnwrapAfterTransfer(address,uint8,uint256,uint256,uint56,uint64,address) (runs: 1028, μ: 273152, ~: 288734) -ClawbackTest:testUnwrapByInvalidOperator(address,address,uint8,uint256,uint256,uint56) (runs: 1028, μ: 232781, ~: 259415) -ClawbackTest:testUnwrapByOperator(address,address,uint8,uint256,uint256,uint56,uint64) (runs: 1028, μ: 268314, ~: 276271) -ClawbackTest:testUnwrapInvalidAmount(address,uint8,uint256,uint256,uint256,uint56) (runs: 1027, μ: 232310, ~: 258241) -ClawbackTest:testUnwrapInvalidToken(address,uint8,uint256,uint256,uint256,uint56) (runs: 1028, μ: 237759, ~: 263539) -ClawbackTest:testUnwrapTokenLocked(address,uint8,uint256,uint256,uint56) (runs: 1028, μ: 230381, ~: 255596) -ClawbackTest:testUpdateTemplateAdmin(address,address,uint56,bool,bool) (runs: 1028, μ: 76260, ~: 76261) -ClawbackTest:testUpdateTemplateAdminInvalidAdmin() (gas: 49852) -ClawbackTest:testUpdateTemplateAdminInvalidCaller(address,address,bool) (runs: 1028, μ: 63323, ~: 63323) -ClawbackTest:testUpdateTemplateInvalidCaller(address,address,bool,uint56,bool,bool) (runs: 1028, μ: 62583, ~: 50111) -ClawbackTest:testUpdateTemplateInvalidDestructionOnly() (gas: 49760) -ClawbackTest:testUpdateTemplateInvalidDuration(address,uint56,bool,bool,uint56) (runs: 1027, μ: 51268, ~: 51268) -ClawbackTest:testUpdateTemplateInvalidTransferOpen() (gas: 50208) -ClawbackTest:testUpdateTemplateOperator(address,address,bool) (runs: 1028, μ: 67035, ~: 67035) -ClawbackTest:testUpdateTemplateOperatorInvalidCaller(address,address,bool,address,bool) (runs: 1028, μ: 63109, ~: 50285) -ClawbackTest:testUpdateTemplateValid(address,uint56,bool,bool,uint56,bool,bool) (runs: 1028, μ: 59341, ~: 59459) -ClawbackTest:testWrap(address,uint8,uint256,uint256,address) (runs: 1028, μ: 254502, ~: 281166) -ClawbackTest:testWrapInvalidAmount(address,uint8,uint256,uint256,address) (runs: 1028, μ: 208991, ~: 221861) -ClawbackTest:testWrapInvalidRewrapping(uint8,uint256,uint256,uint56,address) (runs: 1028, μ: 227562, ~: 254805) -ClawbackTest:testWrapInvalidTemplate(uint32,uint8,uint256,uint256,address) (runs: 1028, μ: 106339, ~: 115140) -ClawbackTest:testWrapInvalidTokenType(address,uint8,uint256,uint256) (runs: 1026, μ: 144846, ~: 152283) -ERC1155ItemsTest:testBatchMintOwner(uint256[],uint256[]) (runs: 1027, μ: 576972, ~: 587485) -ERC1155ItemsTest:testBatchMintWithRole(address,uint256[],uint256[]) (runs: 1028, μ: 661530, ~: 671805) -ERC1155ItemsTest:testBurnBatchInvalidOwnership(address,uint256[],uint256[]) (runs: 1028, μ: 230735, ~: 233624) -ERC1155ItemsTest:testBurnBatchSuccess(address,uint256[],uint256[],uint256[]) (runs: 1028, μ: 197931, ~: 196185) -ERC1155ItemsTest:testBurnInvalidOwnership(address,uint256,uint256,uint256) (runs: 1025, μ: 109180, ~: 110870) -ERC1155ItemsTest:testBurnSuccess(address,uint256,uint256,uint256) (runs: 1027, μ: 125850, ~: 125879) -ERC1155ItemsTest:testContractURI() (gas: 83132) -ERC1155ItemsTest:testDefaultRoyalty(address,uint96,uint256) (runs: 1025, μ: 41468, ~: 41468) -ERC1155ItemsTest:testFactoryDetermineAddress(address,address,string,string,string,address,uint96) (runs: 1028, μ: 6719744, ~: 6720586) -ERC1155ItemsTest:testMetadataInvalid(address) (runs: 1028, μ: 66770, ~: 66770) -ERC1155ItemsTest:testMetadataOwner() (gas: 43862) -ERC1155ItemsTest:testMetadataWithRole(address) (runs: 1028, μ: 117392, ~: 117392) -ERC1155ItemsTest:testMintInvalidRole(address) (runs: 1028, μ: 122424, ~: 122424) -ERC1155ItemsTest:testMintOwner(uint256,uint256) (runs: 1028, μ: 107378, ~: 107378) -ERC1155ItemsTest:testMintWithRole(address,uint256,uint256) (runs: 1028, μ: 190440, ~: 191021) -ERC1155ItemsTest:testOwnerHasRoles() (gas: 46365) -ERC1155ItemsTest:testReinitializeFails() (gas: 27986) -ERC1155ItemsTest:testRoyaltyInvalidRole(address,uint256,address,uint96,uint256) (runs: 1024, μ: 121054, ~: 121054) -ERC1155ItemsTest:testRoyaltyWithRole(address,uint256,address,uint96,uint256) (runs: 1024, μ: 154232, ~: 154355) -ERC1155ItemsTest:testSelectorCollision() (gas: 82659) -ERC1155ItemsTest:testSupportsInterface() (gas: 34330) -ERC1155ItemsTest:testTokenRoyalty(uint256,address,uint96,uint256) (runs: 1024, μ: 65161, ~: 65161) -ERC1155PackTest:testCantRefundAfterReveal(address) (runs: 1028, μ: 317487, ~: 320587) -ERC1155PackTest:testCommitNoBalance(address) (runs: 1028, μ: 33287, ~: 33287) -ERC1155PackTest:testCommitPendingReveal(address) (runs: 1028, μ: 105326, ~: 105312) -ERC1155PackTest:testCommitWithBalance(address) (runs: 1028, μ: 104546, ~: 104532) -ERC1155PackTest:testFactoryDetermineAddress(address,address,string,string,string,address,uint96,bytes32,uint256) (runs: 1028, μ: 7598577, ~: 7598546) -ERC1155PackTest:testFinalRevealSuccess(address,uint256,uint256) (runs: 1028, μ: 12422161, ~: 11966859) -ERC1155PackTest:testGetRevealIdxInvalidCommit(address) (runs: 1028, μ: 107406, ~: 107392) -ERC1155PackTest:testGetRevealIdxNoCommit(address) (runs: 1028, μ: 29067, ~: 29067) -ERC1155PackTest:testGetRevealIdxSuccess(address) (runs: 1028, μ: 113390, ~: 113376) -ERC1155PackTest:testOwnerHasRoles() (gas: 52681) -ERC1155PackTest:testRefundExpiredCommit(address) (runs: 1028, μ: 158294, ~: 158280) -ERC1155PackTest:testRefundNoCommit(address) (runs: 1028, μ: 26072, ~: 26072) -ERC1155PackTest:testRefundPendingReveal(address) (runs: 1028, μ: 105614, ~: 105600) -ERC1155PackTest:testReinitializeFails() (gas: 206964) -ERC1155PackTest:testRevealAfterAllOpened(address) (runs: 1028, μ: 784444, ~: 790195) -ERC1155PackTest:testRevealInvalidPackContent(address) (runs: 1026, μ: 191428, ~: 191678) -ERC1155PackTest:testRevealInvalidRevealIdx(address) (runs: 1026, μ: 192196, ~: 191024) -ERC1155PackTest:testRevealReentryAttack() (gas: 643612) -ERC1155PackTest:testRevealSuccess(address) (runs: 1028, μ: 318332, ~: 322017) -ERC1155PackTest:testSelectorCollision() (gas: 105145) -ERC1155PackTest:testSupportsInterface() (gas: 31451) -ERC1155SaleTest:testERC20Mint(bool,address,uint256,uint256) (runs: 1028, μ: 3473731, ~: 723249) -ERC1155SaleTest:testERC20MintFailPaidETH(bool,address,uint256,uint256) (runs: 1028, μ: 3381761, ~: 625628) -ERC1155SaleTest:testFactoryDetermineAddress(address,address,address) (runs: 1028, μ: 5561583, ~: 5561583) -ERC1155SaleTest:testFreeGlobalMint(bool,address,uint256,uint256) (runs: 1028, μ: 2919148, ~: 169358) -ERC1155SaleTest:testFreeTokenMint(bool,address,uint256,uint256) (runs: 1028, μ: 2966622, ~: 216098) -ERC1155SaleTest:testMerkleFailBadProof(address[],address,uint256,bool) (runs: 1028, μ: 282147, ~: 280398) -ERC1155SaleTest:testMerkleFailNoProof(address[],address,uint256,bool) (runs: 1028, μ: 278053, ~: 276270) -ERC1155SaleTest:testMerkleReuseFail(address[],uint256,uint256,bool) (runs: 1028, μ: 411004, ~: 411470) -ERC1155SaleTest:testMerkleSuccess(address[],uint256,uint256,bool) (runs: 1028, μ: 402432, ~: 402896) -ERC1155SaleTest:testMerkleSuccessGlobalMultiple(address[],uint256,uint256[]) (runs: 1028, μ: 482481, ~: 490791) -ERC1155SaleTest:testMintExpiredGlobalFail(bool,address,uint256,uint256,uint64,uint64) (runs: 1028, μ: 2859205, ~: 99797) -ERC1155SaleTest:testMintExpiredSingleFail(bool,address,uint256,uint256,uint64,uint64) (runs: 1028, μ: 2859496, ~: 100087) -ERC1155SaleTest:testMintFailMaxTotal(bool,address,uint256,uint256) (runs: 1028, μ: 2945662, ~: 188016) -ERC1155SaleTest:testMintFailWrongPaymentToken(bool,address,uint256,uint256,address) (runs: 1028, μ: 3495954, ~: 6235256) -ERC1155SaleTest:testMintGlobalSuccess(bool,address,uint256,uint256) (runs: 1028, μ: 2947936, ~: 198146) -ERC1155SaleTest:testMintGlobalSupplyExceeded(bool,address,uint256,uint256,uint256) (runs: 1028, μ: 2986344, ~: 5765213) -ERC1155SaleTest:testMintGroupSuccess(bool,address,uint256,uint256) (runs: 1028, μ: 3054890, ~: 304365) -ERC1155SaleTest:testMintInactiveFail(bool,address,uint256,uint256) (runs: 1028, μ: 2805586, ~: 51398) -ERC1155SaleTest:testMintInactiveInGroupFail(bool,address,uint256,uint256) (runs: 1028, μ: 2862666, ~: 108722) -ERC1155SaleTest:testMintInactiveSingleFail(bool,address,uint256,uint256) (runs: 1028, μ: 2860460, ~: 106515) -ERC1155SaleTest:testMintSingleSuccess(bool,address,uint256,uint256) (runs: 1028, μ: 2947989, ~: 198196) -ERC1155SaleTest:testMintTokenSupplyExceeded(bool,address,uint256,uint256,uint256) (runs: 1028, μ: 2986439, ~: 5765311) -ERC1155SaleTest:testSelectorCollision() (gas: 51971) -ERC1155SaleTest:testSupportsInterface() (gas: 10893) -ERC1155SaleTest:testWithdrawERC20(bool,address,uint256) (runs: 1028, μ: 3325567, ~: 6096515) -ERC1155SaleTest:testWithdrawETH(bool,address,uint256) (runs: 1028, μ: 2959877, ~: 5721098) -ERC1155SaleTest:testWithdrawFail(bool,address,uint256) (runs: 1028, μ: 3302031, ~: 6024129) -ERC1155SoulboundTest:testBatchBurnBlocked(uint256[],uint256[]) (runs: 1028, μ: 47733, ~: 47797) -ERC1155SoulboundTest:testBatchMintAllowed(address,uint256) (runs: 1028, μ: 110185, ~: 110185) -ERC1155SoulboundTest:testBurnBlocked(uint256,uint256) (runs: 1028, μ: 25924, ~: 25924) -ERC1155SoulboundTest:testFactoryDetermineAddress(address,address,string,string,string,string,address,uint96) (runs: 1027, μ: 7042333, ~: 7041442) -ERC1155SoulboundTest:testOwnerHasRoles() (gas: 52087) -ERC1155SoulboundTest:testReinitializeFails() (gas: 34614) -ERC1155SoulboundTest:testSelectorCollision() (gas: 90031) -ERC1155SoulboundTest:testSupportsInterface() (gas: 31363) -ERC1155SoulboundTest:testTransferLocked(address,address,uint256) (runs: 1027, μ: 115056, ~: 115056) -ERC1155SoulboundTest:testTransferLockedOperator(address,address,address,uint256) (runs: 1027, μ: 148322, ~: 148322) -ERC1155SoulboundTest:testTransferUnlocked(address,address,uint256) (runs: 1027, μ: 131318, ~: 131318) -ERC1155SoulboundTest:testTransferUnlockedOperator(address,address,address,uint256) (runs: 1027, μ: 165064, ~: 165064) -ERC1155SoulboundTest:testUnlockInvalidRole(address) (runs: 1028, μ: 51725, ~: 51725) -ERC20ItemsTest:testBurnInsufficient(address,uint256,uint256) (runs: 1026, μ: 81154, ~: 82008) -ERC20ItemsTest:testBurnSuccess(address,uint256,uint256) (runs: 1026, μ: 90239, ~: 90239) -ERC20ItemsTest:testFactoryDetermineAddress(address,address,string,string,uint8) (runs: 1028, μ: 5250616, ~: 5251395) -ERC20ItemsTest:testInitValues() (gas: 38152) -ERC20ItemsTest:testMintInvalidRole(address,uint256) (runs: 1028, μ: 67321, ~: 67321) -ERC20ItemsTest:testMintOwner(uint256) (runs: 1027, μ: 80602, ~: 80602) -ERC20ItemsTest:testMintWithRole(address,uint256) (runs: 1028, μ: 164406, ~: 164406) -ERC20ItemsTest:testOwnerHasRoles() (gas: 35476) -ERC20ItemsTest:testReinitializeFails() (gas: 27010) -ERC20ItemsTest:testSelectorCollision() (gas: 61795) -ERC20ItemsTest:testSupportsInterface() (gas: 31231) -ERC721ItemsTest:testBurnBatchInvalidOwnership(address) (runs: 1028, μ: 112693, ~: 112693) -ERC721ItemsTest:testBurnBatchSuccess(address) (runs: 1028, μ: 174325, ~: 174325) -ERC721ItemsTest:testBurnInvalidOwnership(address) (runs: 1028, μ: 109892, ~: 109892) -ERC721ItemsTest:testBurnSuccess(address) (runs: 1028, μ: 138130, ~: 138130) -ERC721ItemsTest:testContractURI() (gas: 85853) -ERC721ItemsTest:testDefaultRoyalty(address,uint96,uint256) (runs: 1025, μ: 41445, ~: 41445) -ERC721ItemsTest:testFactoryDetermineAddress(address,address,string,string,string,string,address,uint96) (runs: 1028, μ: 6794617, ~: 6793149) -ERC721ItemsTest:testMetadataInvalid(address) (runs: 1028, μ: 69188, ~: 69188) -ERC721ItemsTest:testMetadataOwner() (gas: 130207) -ERC721ItemsTest:testMetadataWithRole(address) (runs: 1028, μ: 117459, ~: 117459) -ERC721ItemsTest:testMintInvalidRole(address) (runs: 1028, μ: 68300, ~: 68300) -ERC721ItemsTest:testMintMultiple() (gas: 116440) -ERC721ItemsTest:testMintOwner() (gas: 103203) -ERC721ItemsTest:testMintWithRole(address) (runs: 1028, μ: 187295, ~: 187295) -ERC721ItemsTest:testNameAndSymbol() (gas: 90129) -ERC721ItemsTest:testOwnerHasRoles() (gas: 46710) -ERC721ItemsTest:testReinitializeFails() (gas: 28551) -ERC721ItemsTest:testRoyaltyInvalidRole(address,uint256,address,uint96,uint256) (runs: 1024, μ: 125741, ~: 125741) -ERC721ItemsTest:testRoyaltyWithRole(address,uint256,address,uint96,uint256) (runs: 1024, μ: 154151, ~: 154333) -ERC721ItemsTest:testSelectorCollision() (gas: 95069) -ERC721ItemsTest:testSupportsInterface() (gas: 37278) -ERC721ItemsTest:testTokenMetadata() (gas: 174823) -ERC721ItemsTest:testTokenRoyalty(uint256,address,uint96,uint256) (runs: 1025, μ: 65223, ~: 65223) -ERC721SaleTest:testERC20Mint(bool,address,uint256) (runs: 1024, μ: 3174028, ~: 722632) -ERC721SaleTest:testERC20MintFailMaxTotal(bool,address,uint256) (runs: 1024, μ: 3051242, ~: 573949) -ERC721SaleTest:testERC20MintFailPaidETH(bool,address,uint256) (runs: 1024, μ: 3035137, ~: 557844) -ERC721SaleTest:testETHMintFailMaxTotal(bool,address,uint256) (runs: 1024, μ: 2554177, ~: 76818) -ERC721SaleTest:testFactoryDetermineAddress(address,address,address) (runs: 1028, μ: 5086545, ~: 5086545) -ERC721SaleTest:testFreeMint(bool,address,uint256) (runs: 1024, μ: 2621252, ~: 169785) -ERC721SaleTest:testMerkleFailBadProof(address[],address) (runs: 1028, μ: 272761, ~: 269060) -ERC721SaleTest:testMerkleFailNoProof(address[],address) (runs: 1028, μ: 268807, ~: 265098) -ERC721SaleTest:testMerkleReuseFail(address[],uint256) (runs: 1028, μ: 382280, ~: 378955) -ERC721SaleTest:testMerkleSuccess(address[],uint256) (runs: 1028, μ: 378596, ~: 375281) -ERC721SaleTest:testMintExpiredFail(bool,address,uint256,uint64,uint64) (runs: 1024, μ: 2684805, ~: 2676217) -ERC721SaleTest:testMintFailWrongPaymentToken(bool,address,uint256,address) (runs: 1024, μ: 3013293, ~: 530954) -ERC721SaleTest:testMintInactiveFail(bool,address,uint256) (runs: 1024, μ: 2505594, ~: 27994) -ERC721SaleTest:testMintSuccess(bool,address,uint256) (runs: 1024, μ: 2650344, ~: 198877) -ERC721SaleTest:testMintSupplyExceeded(bool,address,uint256,uint256) (runs: 1024, μ: 2652755, ~: 132241) -ERC721SaleTest:testSelectorCollision() (gas: 44619) -ERC721SaleTest:testSupportsInterface() (gas: 10884) -ERC721SaleTest:testWithdrawERC20(bool,address,uint256) (runs: 1028, μ: 3098106, ~: 5620614) -ERC721SaleTest:testWithdrawETH(bool,address,uint256) (runs: 1028, μ: 2721884, ~: 5245508) -ERC721SaleTest:testWithdrawFail(bool,address,uint256) (runs: 1028, μ: 3059309, ~: 5548963) -ERC721SoulboundTest:testFactoryDetermineAddress(address,address,string,string,string,string,address,uint96) (runs: 1028, μ: 7056085, ~: 7054935) -ERC721SoulboundTest:testOwnerHasRoles() (gas: 52377) -ERC721SoulboundTest:testReinitializeFails() (gas: 35172) -ERC721SoulboundTest:testSelectorCollision() (gas: 102395) -ERC721SoulboundTest:testSupportsInterface() (gas: 40208) -ERC721SoulboundTest:testTransferLocked(address,address) (runs: 1028, μ: 115439, ~: 115439) -ERC721SoulboundTest:testTransferLockedOperator(address,address,address) (runs: 1028, μ: 148256, ~: 148256) -ERC721SoulboundTest:testTransferUnlocked(address,address) (runs: 1028, μ: 151384, ~: 151384) -ERC721SoulboundTest:testTransferUnlockedOperator(address,address,address) (runs: 1028, μ: 184150, ~: 184150) -ERC721SoulboundTest:testUnlockInvalidRole(address) (runs: 1028, μ: 54197, ~: 54197) -PaymentCombinerTest:testDetermineAddress(address[],uint256[]) (runs: 1028, μ: 814948, ~: 822377) -PaymentCombinerTest:testListPayeeSplitters(address[],address[],uint256[],uint256[]) (runs: 1028, μ: 1595027, ~: 1610298) -PaymentCombinerTest:testListPayeeSplittersOffsetLimit(address,address[][],uint256[],uint256,uint256) (runs: 1028, μ: 13974939, ~: 4815839) -PaymentCombinerTest:testListReleasableERC20(uint256,address[],address[],uint256[],uint256[]) (runs: 1027, μ: 1706018, ~: 1721446) -PaymentCombinerTest:testListReleasableNative(uint256,address[],address[],uint256[],uint256[]) (runs: 1027, μ: 1634450, ~: 1649878) -PaymentCombinerTest:testListReleaseERC20(uint256,address[],address[],uint256[],uint256[]) (runs: 1027, μ: 1839912, ~: 1855340) -PaymentCombinerTest:testListReleaseNative(uint256,address[],address[],uint256[],uint256[]) (runs: 1027, μ: 1775344, ~: 1790797) -PaymentCombinerTest:testRepeatedDeploysFail(address[],uint256[]) (runs: 1028, μ: 1040384223, ~: 1040390557) -PaymentCombinerTest:testSupportsInterface() (gas: 10684) -PaymentsTest:testMakePaymentExpired(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),uint64,bool) (runs: 1026, μ: 168772, ~: 172152) -PaymentsTest:testMakePaymentFailedChainedCall(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bytes,bool) (runs: 1028, μ: 242384, ~: 235855) -PaymentsTest:testMakePaymentInvalidPayment(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1028, μ: 106726, ~: 107036) -PaymentsTest:testMakePaymentInvalidSignature(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1028, μ: 58165, ~: 58848) -PaymentsTest:testMakePaymentInvalidTokenSettingsERC20(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),uint256,bool) (runs: 1028, μ: 99741, ~: 83726) -PaymentsTest:testMakePaymentInvalidTokenSettingsERC721(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1028, μ: 99951, ~: 100091) -PaymentsTest:testMakePaymentSuccess(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1028, μ: 201134, ~: 202083) -PaymentsTest:testMakePaymentSuccessChainedCall(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1028, μ: 274134, ~: 273074) -PaymentsTest:testMakePaymentSuccessMultiplePaymentRecips(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),address,bool) (runs: 1026, μ: 224542, ~: 226058) -PaymentsTest:testPerformChainedCallInvalidCall(bytes,bool) (runs: 1028, μ: 60195, ~: 44370) -PaymentsTest:testPerformChainedCallInvalidSignature(address,uint8,uint256,uint256,address,bool) (runs: 1028, μ: 57863, ~: 52500) -PaymentsTest:testPerformChainedCallSuccess(uint8,uint256,uint256,address,bool) (runs: 1028, μ: 131737, ~: 130345) -PaymentsTest:testSelectorCollision() (gas: 37511) -PaymentsTest:testSupportsInterface() (gas: 28390) -PaymentsTest:testUpdateSignerInvalidSender(address,address) (runs: 1028, μ: 28685, ~: 28685) -PaymentsTest:testUpdateSignerSuccess(address) (runs: 1028, μ: 35653, ~: 35677) -SequenceProxyFactoryTest:testAddressCompute() (gas: 1021270) -SequenceProxyFactoryTest:testDeployProxy() (gas: 1021715) -SequenceProxyFactoryTest:testDeployProxyAfterUpgrade() (gas: 1033634) -SequenceProxyFactoryTest:testDuplicateDeploysFail() (gas: 1040461625) -SequenceProxyFactoryTest:testProxyOwnerUpgrade() (gas: 1048467) -SequenceProxyFactoryTest:testProxyOwnerUpgradeUnaffectedByBeaconUpgrades() (gas: 1063273) -SequenceProxyFactoryTest:testUpgradeAfterDeploy() (gas: 1036252) \ No newline at end of file +ClawbackMetadataTest:testDurationAndUnlocksAt() (gas: 900624) +ClawbackMetadataTest:testMetadataPropertiesERC1155((uint8,uint32,uint56,uint256),(bool,bool,uint56,address)) (runs: 1044, μ: 242392, ~: 238164) +ClawbackMetadataTest:testMetadataPropertiesERC20((uint8,uint32,uint56,uint256),(bool,bool,uint56,address)) (runs: 1044, μ: 292816, ~: 293810) +ClawbackMetadataTest:testMetadataPropertiesERC721((uint8,uint32,uint56,uint256),(bool,bool,uint56,address)) (runs: 1044, μ: 382900, ~: 378747) +ClawbackMetadataTest:testSupportsInterface() (gas: 14651) +ClawbackTest:testAddTemplate(address,uint56,bool,bool) (runs: 1044, μ: 64800, ~: 64800) +ClawbackTest:testAddTemplateTransferer(address,address) (runs: 1044, μ: 103476, ~: 103476) +ClawbackTest:testAddTemplateTransfererInvalidCaller(address,address,bool,address) (runs: 1044, μ: 87042, ~: 101688) +ClawbackTest:testAddToWrap(address,uint8,uint256,uint256,uint56,address,uint64) (runs: 1036, μ: 365801, ~: 343435) +ClawbackTest:testAddToWrapInvalidWrappedId(uint256,uint256,address) (runs: 1044, μ: 18728, ~: 18728) +ClawbackTest:testClawback(uint8,uint256,uint256,uint56,address,address) (runs: 1044, μ: 344005, ~: 337026) +ClawbackTest:testClawbackAfterTransfer(uint8,uint256,uint256,uint56,address,address,address) (runs: 1044, μ: 390136, ~: 385897) +ClawbackTest:testClawbackDestructionOnly(uint8,uint256,uint256,uint56,address) (runs: 1044, μ: 343547, ~: 339220) +ClawbackTest:testClawbackDestructionOnlyInvalidReceiver(uint8,uint256,uint256,uint56,address,address) (runs: 1044, μ: 315288, ~: 304890) +ClawbackTest:testClawbackInvalidCaller(uint8,uint256,uint256,uint56,address,address) (runs: 1044, μ: 264354, ~: 254123) +ClawbackTest:testClawbackInvalidUnlocked(uint8,uint256,uint256,uint56,address,address) (runs: 1044, μ: 303931, ~: 293533) +ClawbackTest:testEmergencyClawback(uint8,uint256,uint256,uint56,address,address) (runs: 1044, μ: 359551, ~: 352571) +ClawbackTest:testEmergencyClawbackAfterTransfer(uint8,uint256,uint256,uint56,address,address,address) (runs: 1044, μ: 405181, ~: 401386) +ClawbackTest:testEmergencyClawbackDestructionOnly(uint8,uint256,uint256,uint56,address) (runs: 1044, μ: 358275, ~: 353947) +ClawbackTest:testEmergencyClawbackDestructionOnlyInvalidReceiver(uint8,uint256,uint256,uint56,address,address) (runs: 1044, μ: 315426, ~: 305028) +ClawbackTest:testEmergencyClawbackInvalidCaller(uint8,uint256,uint256,uint56,address,address) (runs: 1044, μ: 263018, ~: 252787) +ClawbackTest:testEmergencyClawbackInvalidUnlocked(uint8,uint256,uint256,uint56,address,address) (runs: 1044, μ: 303959, ~: 293561) +ClawbackTest:testPreventsOnERC1155Received(uint256,uint256) (runs: 1044, μ: 111284, ~: 110667) +ClawbackTest:testPreventsOnERC1155Received(uint256,uint256,uint256,uint256) (runs: 1044, μ: 177254, ~: 176117) +ClawbackTest:testPreventsOnERC721Received(uint256) (runs: 1044, μ: 83566, ~: 83561) +ClawbackTest:testSupportsInterface() (gas: 25404) +ClawbackTest:testTransferByTransfererAsFrom(uint8,uint256,uint256,uint56,uint64,bool,address,bool) (runs: 1044, μ: 327349, ~: 315235) +ClawbackTest:testTransferByTransfererAsOperator(uint8,uint256,uint256,uint56,uint64,bool,address,address,bool) (runs: 1044, μ: 353659, ~: 343477) +ClawbackTest:testTransferByTransfererAsTo(uint8,uint256,uint256,uint56,uint64,bool,address,bool) (runs: 1044, μ: 327921, ~: 315807) +ClawbackTest:testTransferByTransfererNotApproved(uint8,uint256,uint256,uint56,uint64,bool,address,address,bool) (runs: 1044, μ: 315186, ~: 305690) +ClawbackTest:testTransferInvalidOperator(uint8,uint256,uint256,uint56,address,address,bool) (runs: 1044, μ: 310744, ~: 301414) +ClawbackTest:testTransferOpen(uint8,uint256,uint256,uint56,uint64,address) (runs: 1044, μ: 295368, ~: 286947) +ClawbackTest:testUnwrap(address,uint8,uint256,uint256,uint56,uint64) (runs: 1044, μ: 292764, ~: 284935) +ClawbackTest:testUnwrapAfterTransfer(address,uint8,uint256,uint256,uint56,uint64,address) (runs: 1044, μ: 345519, ~: 340070) +ClawbackTest:testUnwrapByInvalidOperator(address,address,uint8,uint256,uint256,uint56) (runs: 1044, μ: 264990, ~: 255362) +ClawbackTest:testUnwrapByOperator(address,address,uint8,uint256,uint256,uint56,uint64) (runs: 1044, μ: 333698, ~: 327035) +ClawbackTest:testUnwrapInvalidAmount(address,uint8,uint256,uint256,uint256,uint56) (runs: 1044, μ: 264903, ~: 255072) +ClawbackTest:testUnwrapInvalidToken(address,uint8,uint256,uint256,uint256,uint56) (runs: 1044, μ: 269425, ~: 259896) +ClawbackTest:testUnwrapTokenLocked(address,uint8,uint256,uint256,uint56) (runs: 1044, μ: 257224, ~: 249299) +ClawbackTest:testUpdateTemplateAdmin(address,address,uint56,bool,bool) (runs: 1043, μ: 130471, ~: 130474) +ClawbackTest:testUpdateTemplateAdminInvalidAdmin() (gas: 71078) +ClawbackTest:testUpdateTemplateAdminInvalidCaller(address,address,bool) (runs: 1044, μ: 87395, ~: 72778) +ClawbackTest:testUpdateTemplateInvalidCaller(address,address,bool,uint56,bool,bool) (runs: 1044, μ: 87592, ~: 102011) +ClawbackTest:testUpdateTemplateInvalidDestructionOnly() (gas: 71730) +ClawbackTest:testUpdateTemplateInvalidDuration(address,uint56,bool,bool,uint56) (runs: 1034, μ: 74349, ~: 74352) +ClawbackTest:testUpdateTemplateInvalidTransferOpen() (gas: 72284) +ClawbackTest:testUpdateTemplateOperator(address,address,bool) (runs: 1044, μ: 93324, ~: 83438) +ClawbackTest:testUpdateTemplateOperatorInvalidCaller(address,address,bool,address,bool) (runs: 1044, μ: 87398, ~: 72782) +ClawbackTest:testUpdateTemplateValid(address,uint56,bool,bool,uint56,bool,bool) (runs: 1044, μ: 86327, ~: 85437) +ClawbackTest:testWrap(address,uint8,uint256,uint256,address) (runs: 1044, μ: 321319, ~: 316791) +ClawbackTest:testWrapInvalidAmount(address,uint8,uint256,uint256,address) (runs: 1044, μ: 238441, ~: 236197) +ClawbackTest:testWrapInvalidRewrapping(uint8,uint256,uint256,uint56,address) (runs: 1044, μ: 255709, ~: 246910) +ClawbackTest:testWrapInvalidTemplate(uint32,uint8,uint256,uint256,address) (runs: 1044, μ: 112492, ~: 107094) +ClawbackTest:testWrapInvalidTokenType(address,uint8,uint256,uint256) (runs: 1039, μ: 169975, ~: 162738) +ERC1155HolderTest:testClaimBatchTokensToEOA(address,address,uint256[],uint256[],bool) (runs: 1040, μ: 1485864, ~: 1506508) +ERC1155HolderTest:testClaimBatchTokensToRecipient(address,uint256[],uint256[],bool) (runs: 1040, μ: 1483400, ~: 1515303) +ERC1155HolderTest:testClaimSingleTokenToEOA(address,address,uint256,uint256,bool) (runs: 1042, μ: 202426, ~: 202401) +ERC1155HolderTest:testClaimSingleTokenToRecipient(address,uint256,uint256,bool) (runs: 1043, μ: 200693, ~: 200668) +ERC1155HolderTest:testClaimantDecodingAddressZero(bool) (runs: 1044, μ: 24177, ~: 24796) +ERC1155HolderTest:testClaimantDecodingInvalidData(bytes) (runs: 1032, μ: 25719, ~: 25707) +ERC1155HolderTest:testRecipientGasUsage(address,address,uint256,uint256) (runs: 1044, μ: 14046, ~: 14046) +ERC1155HolderTest:testRecipientGasUsageBatch(address,address,uint256[],uint256[]) (runs: 1044, μ: 163667, ~: 165499) +ERC1155HolderTest:testSupportsInterface() (gas: 14573) +ERC1155HolderTest:testTransferAddsClaimForClaimant(address,address,uint256,uint256,bool) (runs: 1042, μ: 186134, ~: 185985) +ERC1155HolderTest:testTransferAddsClaimForClaimantBatch(address,address,uint256[],uint256[],bool) (runs: 1040, μ: 1254729, ~: 1272233) +ERC1155ItemsTest:testBatchMintOwner(uint256[],uint256[]) (runs: 1042, μ: 683869, ~: 698070) +ERC1155ItemsTest:testBatchMintWithRole(address,uint256[],uint256[]) (runs: 1042, μ: 779432, ~: 795439) +ERC1155ItemsTest:testBurnBatchInvalidOwnership(address,uint256[],uint256[]) (runs: 1043, μ: 296302, ~: 297719) +ERC1155ItemsTest:testBurnBatchSuccess(address,uint256[],uint256[],uint256[]) (runs: 1043, μ: 310554, ~: 308565) +ERC1155ItemsTest:testBurnInvalidOwnership(address,uint256,uint256,uint256) (runs: 1031, μ: 136002, ~: 137103) +ERC1155ItemsTest:testBurnSuccess(address,uint256,uint256,uint256) (runs: 1037, μ: 173281, ~: 173281) +ERC1155ItemsTest:testContractURI() (gas: 188123) +ERC1155ItemsTest:testDefaultRoyalty(address,uint96,uint256) (runs: 1027, μ: 63841, ~: 63841) +ERC1155ItemsTest:testFactoryDetermineAddress(address,address,string,string,string,address,uint96,address,bytes32) (runs: 1043, μ: 8325594, ~: 8325565) +ERC1155ItemsTest:testMetadataInvalid(address) (runs: 1044, μ: 190372, ~: 190372) +ERC1155ItemsTest:testMetadataOwner() (gas: 63676) +ERC1155ItemsTest:testMetadataWithRole(address) (runs: 1044, μ: 137827, ~: 137827) +ERC1155ItemsTest:testMintInvalidRole(address) (runs: 1044, μ: 370949, ~: 370949) +ERC1155ItemsTest:testMintOwner(uint256,uint256) (runs: 1043, μ: 123064, ~: 123064) +ERC1155ItemsTest:testMintWithRole(address,uint256,uint256) (runs: 1044, μ: 218823, ~: 219453) +ERC1155ItemsTest:testOwnerHasRoles() (gas: 90616) +ERC1155ItemsTest:testReinitializeFails() (gas: 37633) +ERC1155ItemsTest:testRoyaltyInvalidRole(address,uint256,address,uint96,uint256) (runs: 1031, μ: 369759, ~: 369764) +ERC1155ItemsTest:testRoyaltyWithRole(address,uint256,address,uint96,uint256) (runs: 1031, μ: 208649, ~: 208661) +ERC1155ItemsTest:testSelectorCollision() (gas: 409380) +ERC1155ItemsTest:testSupportsInterface() (gas: 68276) +ERC1155ItemsTest:testTokenRoyalty(uint256,address,uint96,uint256) (runs: 1031, μ: 99221, ~: 99221) +ERC1155PackTest:testCantRefundAfterReveal(address) (runs: 1043, μ: 512181, ~: 534749) +ERC1155PackTest:testCommitNoBalance(address) (runs: 1043, μ: 48701, ~: 48701) +ERC1155PackTest:testCommitPendingReveal(address) (runs: 1043, μ: 131604, ~: 131589) +ERC1155PackTest:testCommitWithBalance(address) (runs: 1043, μ: 131112, ~: 131097) +ERC1155PackTest:testFactoryDetermineAddress(address,address,(address,address,string,string,string,address,uint96,address,bytes32,bytes32,uint256)) (runs: 1044, μ: 9493374, ~: 9492815) +ERC1155PackTest:testFinalRevealSuccess(address,uint256,uint256) (runs: 1043, μ: 22413099, ~: 21881720) +ERC1155PackTest:testGetRevealIdxInvalidCommit(address) (runs: 1043, μ: 134049, ~: 134034) +ERC1155PackTest:testGetRevealIdxNoCommit(address) (runs: 1044, μ: 35586, ~: 35586) +ERC1155PackTest:testGetRevealIdxSuccess(address) (runs: 1043, μ: 145640, ~: 145624) +ERC1155PackTest:testOwnerHasRoles() (gas: 103985) +ERC1155PackTest:testRefundExpiredCommit(address) (runs: 1043, μ: 190512, ~: 190497) +ERC1155PackTest:testRefundNoCommit(address) (runs: 1044, μ: 32098, ~: 32098) +ERC1155PackTest:testRefundPendingReveal(address) (runs: 1043, μ: 131543, ~: 131528) +ERC1155PackTest:testReinitializeFails() (gas: 44303) +ERC1155PackTest:testRevealAfterAllOpened(address) (runs: 1043, μ: 1523305, ~: 1518381) +ERC1155PackTest:testRevealInvalidPackContent(address) (runs: 1037, μ: 324626, ~: 323624) +ERC1155PackTest:testRevealInvalidRevealIdx(address) (runs: 1037, μ: 324840, ~: 323310) +ERC1155PackTest:testRevealReentryAttack() (gas: 1023299) +ERC1155PackTest:testRevealSuccessToHolder(address,address) (runs: 1043, μ: 541161, ~: 575766) +ERC1155PackTest:testRevealSuccessToUser(address) (runs: 1043, μ: 471620, ~: 478210) +ERC1155PackTest:testSelectorCollision() (gas: 513970) +ERC1155PackTest:testSupportsInterface() (gas: 68814) +ERC1155SaleBaseTest:testFactoryDetermineAddress(uint256,address,address,address,address,bytes32) (runs: 1043, μ: 7776341, ~: 7776341) +ERC1155SaleBaseTest:testSelectorCollision() (gas: 258594) +ERC1155SaleBaseTest:testSupportsInterface() (gas: 24785) +ERC1155SaleBaseTest:testWithdrawERC20(bool,address,uint256) (runs: 1044, μ: 7033067, ~: 3163582) +ERC1155SaleBaseTest:testWithdrawETH(bool,address,uint256) (runs: 1044, μ: 3956401, ~: 92134) +ERC1155SaleBaseTest:testWithdrawFail(bool,address,uint256) (runs: 1044, μ: 7183595, ~: 3348224) +ERC1155SaleBaseTest:test_addSaleDetails_fail_invalidStartTime((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)) (runs: 1044, μ: 46009, ~: 46043) +ERC1155SaleBaseTest:test_addSaleDetails_fail_invalidSupply((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)) (runs: 1044, μ: 38085, ~: 37775) +ERC1155SaleBaseTest:test_addSaleDetails_fail_invalidTokenId((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)) (runs: 1044, μ: 44909, ~: 44609) +ERC1155SaleBaseTest:test_addSaleDetails_success((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)[],(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)) (runs: 1044, μ: 17137904, ~: 17016162) +ERC1155SaleBaseTest:test_saleDetailsBatch((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)[]) (runs: 1044, μ: 19943220, ~: 20251419) +ERC1155SaleBaseTest:test_saleDetailsBatch_fail_notFound(uint256[]) (runs: 1044, μ: 159161, ~: 154106) +ERC1155SaleBaseTest:test_saleDetails_fail_notFound(uint256) (runs: 1044, μ: 18978, ~: 18978) +ERC1155SaleBaseTest:test_updateSaleDetails_fail_invalidStartTime((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)) (runs: 1044, μ: 176844, ~: 177659) +ERC1155SaleBaseTest:test_updateSaleDetails_fail_invalidSupply((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)) (runs: 1044, μ: 169161, ~: 169632) +ERC1155SaleBaseTest:test_updateSaleDetails_fail_invalidTokenId((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)) (runs: 1044, μ: 175326, ~: 175807) +ERC1155SaleBaseTest:test_updateSaleDetails_fail_notFound((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256) (runs: 1044, μ: 22707, ~: 22707) +ERC1155SaleBaseTest:test_updateSaleDetails_success((uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32)[],(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256) (runs: 1044, μ: 16688486, ~: 16653059) +ERC1155SaleMintTest:test_mint_fail_afterSale(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 4056224, ~: 218264) +ERC1155SaleMintTest:test_mint_fail_beforeSale(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 4058102, ~: 220867) +ERC1155SaleMintTest:test_mint_fail_incorrectPayment(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 4112513, ~: 259490) +ERC1155SaleMintTest:test_mint_fail_insufficientPaymentERC20(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 4208939, ~: 356081) +ERC1155SaleMintTest:test_mint_fail_invalidArrayLength(uint256[],uint256[]) (runs: 1044, μ: 471345, ~: 471275) +ERC1155SaleMintTest:test_mint_fail_invalidExpectedCost(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 4113027, ~: 259882) +ERC1155SaleMintTest:test_mint_fail_invalidExpectedCostERC20(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 4208526, ~: 355668) +ERC1155SaleMintTest:test_mint_fail_invalidExpectedPaymentToken(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,address) (runs: 1044, μ: 4204000, ~: 8020723) +ERC1155SaleMintTest:test_mint_fail_invalidProofsArrayLength(uint256[],bytes32[][]) (runs: 1044, μ: 9604799, ~: 9078432) +ERC1155SaleMintTest:test_mint_fail_invalidTokenId(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,bool) (runs: 1044, μ: 4127102, ~: 4116523) +ERC1155SaleMintTest:test_mint_fail_noSale(uint256,uint256) (runs: 1044, μ: 24219, ~: 24219) +ERC1155SaleMintTest:test_mint_fail_supplyExceeded(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256) (runs: 1044, μ: 3956309, ~: 214522) +ERC1155SaleMintTest:test_mint_fail_supplyExceededOnSubsequentMint(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 8101311, ~: 405557) +ERC1155SaleMintTest:test_mint_fail_valueOnERC20Payment(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 4215909, ~: 364407) +ERC1155SaleMintTest:test_mint_multiple_success(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256,uint256) (runs: 1044, μ: 4571304, ~: 8392763) +ERC1155SaleMintTest:test_mint_multiple_success_ERC20(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256,uint256) (runs: 1044, μ: 4693199, ~: 8514656) +ERC1155SaleMintTest:test_mint_multiple_success_proof(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256,uint256,address[],uint256,address[],uint256) (runs: 1044, μ: 5986736, ~: 8919144) +ERC1155SaleMintTest:test_mint_repeat_success_proof(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256,uint256,address[],uint256,uint256) (runs: 1042, μ: 4807571, ~: 8531261) +ERC1155SaleMintTest:test_mint_success(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256) (runs: 1044, μ: 4099959, ~: 362020) +ERC1155SaleMintTest:test_mint_successERC20(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256) (runs: 1044, μ: 4201161, ~: 463826) +ERC1155SaleMintTest:test_mint_successERC20_higherExpectedCost(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,uint256) (runs: 1044, μ: 4356502, ~: 508575) +ERC1155SaleMintTest:test_mint_success_proof(bool,address,(uint256,uint256,uint256,address,uint256,uint64,uint64,bytes32),uint256,uint256,address[],uint256) (runs: 1044, μ: 4850721, ~: 1555516) +ERC1155SoulboundTest:testBatchBurnBlocked(uint256[],uint256[]) (runs: 1044, μ: 83026, ~: 82037) +ERC1155SoulboundTest:testBatchMintAllowed(address,uint256) (runs: 1044, μ: 136825, ~: 136825) +ERC1155SoulboundTest:testBurnBlocked(uint256,uint256) (runs: 1044, μ: 31764, ~: 31764) +ERC1155SoulboundTest:testFactoryDetermineAddress(address,address,string,string,string,address,uint96,address,bytes32) (runs: 1043, μ: 8588466, ~: 8588489) +ERC1155SoulboundTest:testOwnerHasRoles() (gas: 103193) +ERC1155SoulboundTest:testReinitializeFails() (gas: 44395) +ERC1155SoulboundTest:testSelectorCollision() (gas: 444126) +ERC1155SoulboundTest:testSupportsInterface() (gas: 68726) +ERC1155SoulboundTest:testTransferLocked(address,address,uint256) (runs: 1042, μ: 148182, ~: 148182) +ERC1155SoulboundTest:testTransferLockedOperator(address,address,address,uint256) (runs: 1042, μ: 194929, ~: 194929) +ERC1155SoulboundTest:testTransferUnlocked(address,address,uint256) (runs: 1042, μ: 175012, ~: 175012) +ERC1155SoulboundTest:testTransferUnlockedOperator(address,address,address,uint256) (runs: 1042, μ: 222413, ~: 222413) +ERC1155SoulboundTest:testUnlockInvalidRole(address) (runs: 1044, μ: 141988, ~: 141988) +ERC20ItemsTest:testBurnInsufficient(address,uint256,uint256) (runs: 1033, μ: 100757, ~: 101836) +ERC20ItemsTest:testBurnSuccess(address,uint256,uint256) (runs: 1035, μ: 120343, ~: 120343) +ERC20ItemsTest:testFactoryDetermineAddress(address,address,string,string,uint8,address,bytes32) (runs: 1043, μ: 7025725, ~: 7026085) +ERC20ItemsTest:testInitValues() (gas: 57510) +ERC20ItemsTest:testMintInvalidRole(address,uint256) (runs: 1042, μ: 193256, ~: 193256) +ERC20ItemsTest:testMintOwner(uint256) (runs: 1043, μ: 99124, ~: 99124) +ERC20ItemsTest:testMintWithRole(address,uint256) (runs: 1042, μ: 196842, ~: 196842) +ERC20ItemsTest:testOwnerHasRoles() (gas: 65748) +ERC20ItemsTest:testReinitializeFails() (gas: 34145) +ERC20ItemsTest:testSelectorCollision() (gas: 316460) +ERC20ItemsTest:testSupportsInterface() (gas: 66090) +ERC721ItemsTest:testBurnBatchInvalidOwnership(address) (runs: 1044, μ: 182156, ~: 182159) +ERC721ItemsTest:testBurnBatchSuccess(address) (runs: 1044, μ: 160906, ~: 160893) +ERC721ItemsTest:testBurnInvalidOwnership(address,uint256) (runs: 1044, μ: 133855, ~: 133592) +ERC721ItemsTest:testBurnSuccess(address,uint256) (runs: 1044, μ: 113167, ~: 112956) +ERC721ItemsTest:testContractURI() (gas: 188325) +ERC721ItemsTest:testDefaultRoyalty(address,uint96,uint256) (runs: 1028, μ: 63841, ~: 63841) +ERC721ItemsTest:testFactoryDetermineAddress(address,address,string,string,string,string,address,uint96,address,bytes32) (runs: 1043, μ: 7870934, ~: 7873494) +ERC721ItemsTest:testMetadataInvalid(address) (runs: 1044, μ: 190504, ~: 190504) +ERC721ItemsTest:testMetadataOwner() (gas: 210357) +ERC721ItemsTest:testMetadataWithRole(address) (runs: 1044, μ: 137827, ~: 137827) +ERC721ItemsTest:testMintCollision(uint256) (runs: 1044, μ: 129860, ~: 129678) +ERC721ItemsTest:testMintCollisionOverSequentialMint(uint256,uint256) (runs: 1044, μ: 276884, ~: 289069) +ERC721ItemsTest:testMintInvalidRole(address,uint256) (runs: 1044, μ: 190672, ~: 190672) +ERC721ItemsTest:testMintMultiple() (gas: 192459) +ERC721ItemsTest:testMintOwner(uint256) (runs: 1044, μ: 123141, ~: 122959) +ERC721ItemsTest:testMintWithRole(address,uint256) (runs: 1044, μ: 220868, ~: 220625) +ERC721ItemsTest:testNameAndSymbol() (gas: 199924) +ERC721ItemsTest:testOwnerHasRoles() (gas: 90836) +ERC721ItemsTest:testReinitializeFails() (gas: 38382) +ERC721ItemsTest:testRoyaltyInvalidRole(address,uint256,address,uint96,uint256) (runs: 1031, μ: 369830, ~: 369830) +ERC721ItemsTest:testRoyaltyWithRole(address,uint256,address,uint96,uint256) (runs: 1031, μ: 208586, ~: 208617) +ERC721ItemsTest:testSelectorCollision() (gas: 432676) +ERC721ItemsTest:testSequentialMintOverSpotMint(uint256,uint256) (runs: 1044, μ: 312479, ~: 324664) +ERC721ItemsTest:testSupportsInterface() (gas: 67398) +ERC721ItemsTest:testTokenMetadata(uint256) (runs: 1044, μ: 307378, ~: 305712) +ERC721ItemsTest:testTokenRoyalty(uint256,address,uint96,uint256) (runs: 1034, μ: 99221, ~: 99221) +ERC721ItemsTest:testTotalSupply(uint256,uint256[]) (runs: 1043, μ: 713746, ~: 717631) +ERC721SaleBaseTest:testFactoryDetermineAddress(address,address,address,address,bytes32) (runs: 1043, μ: 7103963, ~: 7103963) +ERC721SaleBaseTest:testSelectorCollision() (gas: 235188) +ERC721SaleBaseTest:testSupportsInterface() (gas: 24669) +ERC721SaleBaseTest:testWithdrawERC20(bool,address,uint256) (runs: 1044, μ: 6704697, ~: 3161272) +ERC721SaleBaseTest:testWithdrawETH(bool,address,uint256) (runs: 1044, μ: 3629390, ~: 90535) +ERC721SaleBaseTest:testWithdrawFail(bool,address,uint256) (runs: 1044, μ: 6850613, ~: 3348144) +ERC721SaleMintTest:testERC20Mint(bool,address,uint256,uint256) (runs: 1044, μ: 7297511, ~: 10597567) +ERC721SaleMintTest:testERC20MintFailMaxTotal(bool,address,uint256) (runs: 1044, μ: 6846833, ~: 3307498) +ERC721SaleMintTest:testERC20MintFailPaidETH(bool,address,uint256) (runs: 1044, μ: 6831145, ~: 3291810) +ERC721SaleMintTest:testETHMintFailMaxTotal(bool,address,uint256) (runs: 1044, μ: 3666591, ~: 126222) +ERC721SaleMintTest:testFreeMint(bool,address,uint256) (runs: 1044, μ: 4005765, ~: 716356) +ERC721SaleMintTest:testMerkleFailBadProof(address[],address) (runs: 1044, μ: 727203, ~: 744188) +ERC721SaleMintTest:testMerkleFailNoProof(address[],address) (runs: 1044, μ: 717453, ~: 733185) +ERC721SaleMintTest:testMerkleReuseFail(address[],uint256) (runs: 1044, μ: 866528, ~: 888947) +ERC721SaleMintTest:testMerkleSuccess(address[],uint256) (runs: 1044, μ: 854839, ~: 876760) +ERC721SaleMintTest:testMintExpiredFail(bool,address,uint256,uint64,uint64) (runs: 1044, μ: 3680510, ~: 155265) +ERC721SaleMintTest:testMintFailWrongPaymentToken(bool,address,uint256,address) (runs: 1044, μ: 6673450, ~: 3264183) +ERC721SaleMintTest:testMintInactiveFail(bool,address,uint256) (runs: 1044, μ: 3584865, ~: 45995) +ERC721SaleMintTest:testMintSuccess(bool,address,uint256,uint256) (runs: 1044, μ: 4081555, ~: 7385144) +ERC721SaleMintTest:testMintSupplyExceeded(bool,address,uint256,uint256) (runs: 1044, μ: 3733413, ~: 7298069) +ERC721SoulboundTest:testFactoryDetermineAddress(address,address,string,string,string,string,address,uint96,address,bytes32) (runs: 1043, μ: 8113913, ~: 8116426) +ERC721SoulboundTest:testOwnerHasRoles() (gas: 103347) +ERC721SoulboundTest:testReinitializeFails() (gas: 46999) +ERC721SoulboundTest:testSelectorCollision() (gas: 467312) +ERC721SoulboundTest:testSupportsInterface() (gas: 76937) +ERC721SoulboundTest:testTransferLocked(address,address,uint256) (runs: 1042, μ: 147733, ~: 147490) +ERC721SoulboundTest:testTransferLockedOperator(address,address,address,uint256) (runs: 1041, μ: 194381, ~: 194259) +ERC721SoulboundTest:testTransferUnlocked(address,address,uint256) (runs: 1042, μ: 171701, ~: 171458) +ERC721SoulboundTest:testTransferUnlockedOperator(address,address,address,uint256) (runs: 1041, μ: 218973, ~: 218851) +ERC721SoulboundTest:testUnlockInvalidRole(address) (runs: 1044, μ: 141900, ~: 141900) +PaymentCombinerTest:testDetermineAddress(address[],uint256[]) (runs: 1042, μ: 986422, ~: 992930) +PaymentCombinerTest:testListPayeeSplitters(address[],address[],uint256[],uint256[]) (runs: 1042, μ: 1933689, ~: 1950209) +PaymentCombinerTest:testListPayeeSplittersOffsetLimit(address,address[][],uint256[],uint256,uint256) (runs: 1044, μ: 6719227, ~: 6447963) +PaymentCombinerTest:testListReleasableERC20(uint256,address[],address[],uint256[],uint256[]) (runs: 1042, μ: 2088008, ~: 2107028) +PaymentCombinerTest:testListReleasableNative(uint256,address[],address[],uint256[],uint256[]) (runs: 1042, μ: 1995846, ~: 2014866) +PaymentCombinerTest:testListReleaseERC20(uint256,address[],address[],uint256[],uint256[]) (runs: 1042, μ: 2268866, ~: 2287886) +PaymentCombinerTest:testListReleaseNative(uint256,address[],address[],uint256[],uint256[]) (runs: 1042, μ: 2167298, ~: 2186318) +PaymentCombinerTest:testRepeatedDeploysFail(address[],uint256[]) (runs: 1042, μ: 1040392954, ~: 1040400729) +PaymentCombinerTest:testSupportsInterface() (gas: 18403) +PaymentsTest:testMakePaymentExpired(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),uint64,bool) (runs: 1033, μ: 215746, ~: 213324) +PaymentsTest:testMakePaymentFailedChainedCall(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bytes,bool) (runs: 1044, μ: 313424, ~: 322116) +PaymentsTest:testMakePaymentInvalidPayment(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1044, μ: 158063, ~: 178481) +PaymentsTest:testMakePaymentInvalidSignature(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1044, μ: 90738, ~: 101043) +PaymentsTest:testMakePaymentInvalidTokenSettingsERC20(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),uint256,bool) (runs: 1044, μ: 149987, ~: 170789) +PaymentsTest:testMakePaymentInvalidTokenSettingsERC721(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1044, μ: 150559, ~: 171203) +PaymentsTest:testMakePaymentSuccess(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1044, μ: 261610, ~: 267503) +PaymentsTest:testMakePaymentSuccessChainedCall(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),bool) (runs: 1044, μ: 333321, ~: 339740) +PaymentsTest:testMakePaymentSuccessMultiplePaymentRecips(address,(uint256,address,uint8,address,uint256,(address,uint256),uint64,string),address,bool) (runs: 1040, μ: 314600, ~: 322935) +PaymentsTest:testPerformChainedCallInvalidCall(bytes,bool) (runs: 1044, μ: 81338, ~: 61573) +PaymentsTest:testPerformChainedCallInvalidSignature(address,uint8,uint256,uint256,address,bool) (runs: 1044, μ: 89168, ~: 81519) +PaymentsTest:testPerformChainedCallSuccess(uint8,uint256,uint256,address,bool) (runs: 1044, μ: 161166, ~: 157866) +PaymentsTest:testSelectorCollision() (gas: 165828) +PaymentsTest:testSupportsInterface() (gas: 46605) +PaymentsTest:testUpdateSignerInvalidSender(address,address) (runs: 1044, μ: 36362, ~: 36362) +PaymentsTest:testUpdateSignerSuccess(address) (runs: 1044, μ: 48398, ~: 48398) +SequenceProxyFactoryTest:testAddressCompute() (gas: 1171764) +SequenceProxyFactoryTest:testDeployProxy() (gas: 1174506) +SequenceProxyFactoryTest:testDeployProxyAfterUpgrade() (gas: 1190407) +SequenceProxyFactoryTest:testDuplicateDeploysFail() (gas: 1040467047) +SequenceProxyFactoryTest:testProxyOwnerUpgrade() (gas: 1205727) +SequenceProxyFactoryTest:testProxyOwnerUpgradeUnaffectedByBeaconUpgrades() (gas: 1224524) +SequenceProxyFactoryTest:testUpgradeAfterDeploy() (gas: 1193004) +SignalsImplicitModeTest:testAcceptImplicitRequestFailsWhenHookReverts() (gas: 211356) +SignalsImplicitModeTest:testAcceptImplicitRequestFailsWhenNotInitialized() (gas: 1694547) +SignalsImplicitModeTest:testAcceptImplicitRequestWithDelegateCall() (gas: 195975) +SignalsImplicitModeTest:testAcceptImplicitRequestWithFallbackOnly() (gas: 195768) +SignalsImplicitModeTest:testAcceptImplicitRequestWithTransactionCall() (gas: 195689) +SignalsImplicitModeTest:testInitialize() (gas: 164484) +SignalsImplicitModeTest:testSupportsInterface() (gas: 15574) \ No newline at end of file diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index d223cd1..958dcb5 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -3,12 +3,15 @@ pragma solidity ^0.8.18; import { PaymentCombiner } from "../src/payments/PaymentCombiner.sol"; import { PaymentsFactory } from "../src/payments/PaymentsFactory.sol"; -import { ERC1155ItemsFactory } from "../src/tokens/ERC1155/presets/items/ERC1155ItemsFactory.sol"; +import { ERC1155ItemsFactory } from "../src/tokens/ERC1155/presets/items/ERC1155ItemsFactory.sol"; import { ERC1155PackFactory } from "../src/tokens/ERC1155/presets/pack/ERC1155PackFactory.sol"; import { ERC1155SoulboundFactory } from "../src/tokens/ERC1155/presets/soulbound/ERC1155SoulboundFactory.sol"; +import { ERC1155Holder } from "../src/tokens/ERC1155/utility/holder/ERC1155Holder.sol"; import { ERC1155SaleFactory } from "../src/tokens/ERC1155/utility/sale/ERC1155SaleFactory.sol"; + import { ERC20ItemsFactory } from "../src/tokens/ERC20/presets/items/ERC20ItemsFactory.sol"; + import { ERC721ItemsFactory } from "../src/tokens/ERC721/presets/items/ERC721ItemsFactory.sol"; import { ERC721SoulboundFactory } from "../src/tokens/ERC721/presets/soulbound/ERC721SoulboundFactory.sol"; import { ERC721SaleFactory } from "../src/tokens/ERC721/utility/sale/ERC721SaleFactory.sol"; @@ -67,9 +70,11 @@ contract Deploy is SingletonDeployer { salt, pk ); + address holder = + _deployIfNotAlready("ERC1155Holder", abi.encodePacked(type(ERC1155Holder).creationCode), salt, pk); _deployIfNotAlready( "ERC1155PackFactory", - abi.encodePacked(type(ERC1155PackFactory).creationCode, abi.encode(factoryOwner)), + abi.encodePacked(type(ERC1155PackFactory).creationCode, abi.encode(factoryOwner, holder)), salt, pk ); diff --git a/src/tokens/ERC1155/ERC1155BaseToken.sol b/src/tokens/ERC1155/ERC1155BaseToken.sol index ecac6cb..c7cb857 100644 --- a/src/tokens/ERC1155/ERC1155BaseToken.sol +++ b/src/tokens/ERC1155/ERC1155BaseToken.sol @@ -20,10 +20,7 @@ abstract contract ERC1155BaseToken is ERC1155Supply, ERC2981Controlled, SignalsI string public baseURI; string public contractURI; - /** - * Deploy contract. - */ - constructor() { } + bool private _initialized; /** * Initialize the contract. @@ -43,6 +40,10 @@ abstract contract ERC1155BaseToken is ERC1155Supply, ERC2981Controlled, SignalsI address implicitModeValidator, bytes32 implicitModeProjectId ) internal { + if (_initialized) { + revert InvalidInitialization(); + } + name = tokenName; baseURI = tokenBaseURI; contractURI = tokenContractURI; @@ -52,6 +53,8 @@ abstract contract ERC1155BaseToken is ERC1155Supply, ERC2981Controlled, SignalsI _grantRole(METADATA_ADMIN_ROLE, owner); _initializeImplicitMode(owner, implicitModeValidator, implicitModeProjectId); + + _initialized = true; } // diff --git a/src/tokens/ERC1155/extensions/supply/ERC1155Supply.sol b/src/tokens/ERC1155/extensions/supply/ERC1155Supply.sol index 8205ac2..2e7f196 100644 --- a/src/tokens/ERC1155/extensions/supply/ERC1155Supply.sol +++ b/src/tokens/ERC1155/extensions/supply/ERC1155Supply.sol @@ -45,9 +45,14 @@ abstract contract ERC1155Supply is ERC1155, IERC1155Supply { uint256 nMint = _ids.length; uint256 totalAmount = 0; - for (uint256 i = 0; i < nMint; i++) { - totalAmount += _amounts[i]; - tokenSupply[_ids[i]] += _amounts[i]; + for (uint256 i; i < nMint;) { + uint256 amount = _amounts[i]; + totalAmount += amount; + tokenSupply[_ids[i]] += amount; + unchecked { + // Already checked in super._batchMint + ++i; + } } totalSupply += totalAmount; } @@ -76,9 +81,14 @@ abstract contract ERC1155Supply is ERC1155, IERC1155Supply { uint256 nBurn = _ids.length; uint256 totalAmount = 0; - for (uint256 i = 0; i < nBurn; i++) { - tokenSupply[_ids[i]] -= _amounts[i]; - totalAmount += _amounts[i]; + for (uint256 i; i < nBurn;) { + uint256 amount = _amounts[i]; + tokenSupply[_ids[i]] -= amount; + totalAmount += amount; + unchecked { + // Already checked in super._batchBurn + ++i; + } } totalSupply -= totalAmount; } diff --git a/src/tokens/ERC1155/presets/items/ERC1155Items.sol b/src/tokens/ERC1155/presets/items/ERC1155Items.sol index 81e4f39..9b5a884 100644 --- a/src/tokens/ERC1155/presets/items/ERC1155Items.sol +++ b/src/tokens/ERC1155/presets/items/ERC1155Items.sol @@ -11,13 +11,6 @@ contract ERC1155Items is ERC1155BaseToken, IERC1155Items { bytes32 internal constant MINTER_ROLE = keccak256("MINTER_ROLE"); - address private immutable initializer; - bool private initialized; - - constructor() { - initializer = msg.sender; - } - /** * Initialize the contract. * @param owner Owner address @@ -40,18 +33,12 @@ contract ERC1155Items is ERC1155BaseToken, IERC1155Items { address implicitModeValidator, bytes32 implicitModeProjectId ) public virtual { - if (msg.sender != initializer || initialized) { - revert InvalidInitialization(); - } - ERC1155BaseToken._initialize( owner, tokenName, tokenBaseURI, tokenContractURI, implicitModeValidator, implicitModeProjectId ); _setDefaultRoyalty(royaltyReceiver, royaltyFeeNumerator); _grantRole(MINTER_ROLE, owner); - - initialized = true; } // diff --git a/src/tokens/ERC1155/presets/pack/ERC1155Pack.sol b/src/tokens/ERC1155/presets/pack/ERC1155Pack.sol index 9c5586a..11da13c 100644 --- a/src/tokens/ERC1155/presets/pack/ERC1155Pack.sol +++ b/src/tokens/ERC1155/presets/pack/ERC1155Pack.sol @@ -12,14 +12,20 @@ contract ERC1155Pack is ERC1155Items, IERC1155Pack { bytes32 internal constant PACK_ADMIN_ROLE = keccak256("PACK_ADMIN_ROLE"); + address public immutable erc1155Holder; + mapping(uint256 => bytes32) public merkleRoot; mapping(uint256 => uint256) public supply; mapping(uint256 => uint256) public remainingSupply; - mapping(uint256 => mapping(address => uint256)) internal _commitments; + mapping(address => mapping(uint256 => uint256)) internal _commitments; mapping(uint256 => mapping(uint256 => uint256)) internal _availableIndices; - constructor() ERC1155Items() { } + constructor( + address _erc1155Holder + ) { + erc1155Holder = _erc1155Holder; + } /// @inheritdoc ERC1155Items function initialize( @@ -56,12 +62,11 @@ contract ERC1155Pack is ERC1155Items, IERC1155Pack { function commit( uint256 packId ) external { - if (_commitments[packId][msg.sender] != 0) { + if (_commitments[msg.sender][packId] != 0) { revert PendingReveal(); } _burn(msg.sender, packId, 1); - uint256 revealAfterBlock = block.number + 1; - _commitments[packId][msg.sender] = revealAfterBlock; + _commitments[msg.sender][packId] = block.number + 1; emit Commit(msg.sender, packId); } @@ -80,21 +85,33 @@ contract ERC1155Pack is ERC1155Items, IERC1155Pack { revert InvalidProof(); } - delete _commitments[packId][user]; + delete _commitments[user][packId]; remainingSupply[packId]--; // Point this index to the last index's value _availableIndices[packId][randomIndex] = _getIndexOrDefault(remainingSupply[packId], packId); - for (uint256 i = 0; i < packContent.tokenAddresses.length; i++) { + for (uint256 i; i < packContent.tokenAddresses.length;) { + address tokenAddr = packContent.tokenAddresses[i]; + uint256[] memory tokenIds = packContent.tokenIds[i]; if (packContent.isERC721[i]) { - for (uint256 j = 0; j < packContent.tokenIds[i].length; j++) { - IERC721ItemsFunctions(packContent.tokenAddresses[i]).mint(user, packContent.tokenIds[i][j]); + for (uint256 j; j < tokenIds.length;) { + IERC721ItemsFunctions(tokenAddr).mint(user, tokenIds[j]); + unchecked { + ++j; + } } } else { - IERC1155ItemsFunctions(packContent.tokenAddresses[i]).batchMint( - user, packContent.tokenIds[i], packContent.amounts[i], "" - ); + // Send via the holder fallback if available + address to = user; + if (erc1155Holder != address(0) && msg.sender != user) { + to = erc1155Holder; + } + bytes memory packedData = abi.encode(user); + IERC1155ItemsFunctions(tokenAddr).batchMint(to, tokenIds, packContent.amounts[i], packedData); + } + unchecked { + ++i; } } @@ -103,14 +120,14 @@ contract ERC1155Pack is ERC1155Items, IERC1155Pack { /// @inheritdoc IERC1155Pack function refundPack(address user, uint256 packId) external { - uint256 commitment = _commitments[packId][user]; + uint256 commitment = _commitments[user][packId]; if (commitment == 0) { revert NoCommit(); } if (uint256(blockhash(commitment)) != 0 || block.number <= commitment) { revert PendingReveal(); } - delete _commitments[packId][user]; + delete _commitments[user][packId]; _mint(user, packId, 1, ""); } @@ -125,7 +142,7 @@ contract ERC1155Pack is ERC1155Items, IERC1155Pack { revert AllPacksOpened(); } - uint256 commitment = _commitments[packId][user]; + uint256 commitment = _commitments[user][packId]; if (commitment == 0) { revert NoCommit(); } @@ -147,7 +164,7 @@ contract ERC1155Pack is ERC1155Items, IERC1155Pack { function supportsInterface( bytes4 interfaceId ) public view override returns (bool) { - return type(IERC1155Pack).interfaceId == interfaceId || super.supportsInterface(interfaceId); + return interfaceId == type(IERC1155Pack).interfaceId || super.supportsInterface(interfaceId); } } diff --git a/src/tokens/ERC1155/presets/pack/ERC1155PackFactory.sol b/src/tokens/ERC1155/presets/pack/ERC1155PackFactory.sol index dde9811..7df17d2 100644 --- a/src/tokens/ERC1155/presets/pack/ERC1155PackFactory.sol +++ b/src/tokens/ERC1155/presets/pack/ERC1155PackFactory.sol @@ -13,11 +13,10 @@ contract ERC1155PackFactory is IERC1155PackFactory, SequenceProxyFactory { /** * Creates an ERC-1155 Pack Factory. * @param factoryOwner The owner of the ERC-1155 Pack Factory + * @param holderFallback The address of the ERC1155Holder fallback */ - constructor( - address factoryOwner - ) { - ERC1155Pack impl = new ERC1155Pack(); + constructor(address factoryOwner, address holderFallback) { + ERC1155Pack impl = new ERC1155Pack(holderFallback); SequenceProxyFactory._initialize(address(impl), factoryOwner); } diff --git a/src/tokens/ERC1155/presets/soulbound/ERC1155Soulbound.sol b/src/tokens/ERC1155/presets/soulbound/ERC1155Soulbound.sol index ffb09ab..96de1ee 100644 --- a/src/tokens/ERC1155/presets/soulbound/ERC1155Soulbound.sol +++ b/src/tokens/ERC1155/presets/soulbound/ERC1155Soulbound.sol @@ -15,8 +15,6 @@ contract ERC1155Soulbound is ERC1155Items, IERC1155Soulbound { bool internal _transferLocked; - constructor() ERC1155Items() { } - /// @inheritdoc ERC1155Items function initialize( address owner, diff --git a/src/tokens/ERC1155/utility/holder/ERC1155Holder.sol b/src/tokens/ERC1155/utility/holder/ERC1155Holder.sol new file mode 100644 index 0000000..42157ff --- /dev/null +++ b/src/tokens/ERC1155/utility/holder/ERC1155Holder.sol @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.19; + +import { IERC1155 } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol"; +import { IERC1155Receiver, IERC165 } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; + +/** + * An ERC-1155 contract that allows permissive minting. + */ +contract ERC1155Holder is IERC1155Receiver { + + /// @dev Emitted when a claim is added. + event ClaimAdded(address claimant, address tokenAddress, uint256 tokenId, uint256 amount); + /// @dev Emitted when a batch of claims is added. + event ClaimAddedBatch(address claimant, address tokenAddress, uint256[] tokenIds, uint256[] amounts); + + /// @dev Emitted when a claim is claimed. + event Claimed(address claimant, address tokenAddress, uint256 tokenId, uint256 amount); + /// @dev Emitted when a batch of claims is claimed. + event ClaimedBatch(address claimant, address tokenAddress, uint256[] tokenIds, uint256[] amounts); + + /// @dev Error thrown when the claimant is invalid. + error InvalidClaimant(); + + /// @dev claimant -> tokenAddress -> tokenId -> amount + mapping(address => mapping(address => mapping(uint256 => uint256))) public claims; + + /// @dev Claims a token. + /// @param claimant The claimant. + /// @param tokenAddress The token address. + /// @param tokenId The token id. + function claim(address claimant, address tokenAddress, uint256 tokenId) public { + uint256 amount = claims[claimant][tokenAddress][tokenId]; + delete claims[claimant][tokenAddress][tokenId]; + emit Claimed(claimant, tokenAddress, tokenId, amount); + IERC1155(tokenAddress).safeTransferFrom(address(this), claimant, tokenId, amount, ""); + } + + /// @dev Claims a batch of tokens. + /// @param claimant The claimant. + /// @param tokenAddress The token address. + /// @param tokenIds The token ids. + function claimBatch(address claimant, address tokenAddress, uint256[] memory tokenIds) public { + uint256[] memory amounts = new uint256[](tokenIds.length); + for (uint256 i = 0; i < tokenIds.length; i++) { + amounts[i] = claims[claimant][tokenAddress][tokenIds[i]]; + delete claims[claimant][tokenAddress][tokenIds[i]]; + } + emit ClaimedBatch(claimant, tokenAddress, tokenIds, amounts); + IERC1155(tokenAddress).safeBatchTransferFrom(address(this), claimant, tokenIds, amounts, ""); + } + + /// @inheritdoc IERC1155Receiver + /// @param claimData The encoded claimant. + function onERC1155Received( + address, + address, + uint256 tokenId, + uint256 amount, + bytes calldata claimData + ) public virtual override returns (bytes4) { + address claimant = _decodeClaimant(claimData); + address tokenAddress = msg.sender; + claims[claimant][tokenAddress][tokenId] += amount; + emit ClaimAdded(claimant, tokenAddress, tokenId, amount); + return this.onERC1155Received.selector; + } + + /// @inheritdoc IERC1155Receiver + /// @param claimData The encoded claimant. + function onERC1155BatchReceived( + address, + address, + uint256[] calldata tokenIds, + uint256[] calldata amounts, + bytes calldata claimData + ) public virtual override returns (bytes4) { + address claimant = _decodeClaimant(claimData); + address tokenAddress = msg.sender; + for (uint256 i = 0; i < tokenIds.length; i++) { + claims[claimant][tokenAddress][tokenIds[i]] += amounts[i]; + } + emit ClaimAddedBatch(claimant, tokenAddress, tokenIds, amounts); + return this.onERC1155BatchReceived.selector; + } + + /// @dev Decodes the claimant from the claim data. + function _decodeClaimant( + bytes calldata claimData + ) internal pure returns (address claimant) { + if (claimData.length == 20) { + // Packed address format + assembly { + calldatacopy(0, claimData.offset, 20) + claimant := shr(96, mload(0)) + } + } else if (claimData.length == 32) { + // ABI encoded address format + (claimant) = abi.decode(claimData, (address)); + } + if (claimant == address(0)) { + revert InvalidClaimant(); + } + return claimant; + } + + /// @inheritdoc IERC165 + function supportsInterface( + bytes4 interfaceId + ) public view virtual override(IERC165) returns (bool) { + return interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } + +} diff --git a/src/tokens/ERC20/ERC20BaseToken.sol b/src/tokens/ERC20/ERC20BaseToken.sol index aea1cae..52cbbd1 100644 --- a/src/tokens/ERC20/ERC20BaseToken.sol +++ b/src/tokens/ERC20/ERC20BaseToken.sol @@ -18,12 +18,9 @@ abstract contract ERC20BaseToken is ERC20, SignalsImplicitModeControlled { string internal _tokenSymbol; uint8 private _tokenDecimals; - address private immutable _initializer; bool private _initialized; - constructor() ERC20("", "") { - _initializer = msg.sender; - } + constructor() ERC20("", "") { } /** * Initialize contract. @@ -43,7 +40,7 @@ abstract contract ERC20BaseToken is ERC20, SignalsImplicitModeControlled { address implicitModeValidator, bytes32 implicitModeProjectId ) public virtual { - if (msg.sender != _initializer || _initialized) { + if (_initialized) { revert InvalidInitialization(); } diff --git a/src/tokens/ERC721/ERC721BaseToken.sol b/src/tokens/ERC721/ERC721BaseToken.sol index 02fb545..09daa3b 100644 --- a/src/tokens/ERC721/ERC721BaseToken.sol +++ b/src/tokens/ERC721/ERC721BaseToken.sol @@ -21,6 +21,8 @@ abstract contract ERC721BaseToken is ERC721, ERC2981Controlled, SignalsImplicitM string private _tokenSymbol; string private _contractURI; + bool private _initialized; + /** * Initialize contract. * @param owner The owner of the contract @@ -41,6 +43,10 @@ abstract contract ERC721BaseToken is ERC721, ERC2981Controlled, SignalsImplicitM address implicitModeValidator, bytes32 implicitModeProjectId ) internal { + if (_initialized) { + revert InvalidInitialization(); + } + _tokenName = tokenName; _tokenSymbol = tokenSymbol; _tokenBaseURI = tokenBaseURI; @@ -51,6 +57,8 @@ abstract contract ERC721BaseToken is ERC721, ERC2981Controlled, SignalsImplicitM _grantRole(ROYALTY_ADMIN_ROLE, owner); _initializeImplicitMode(owner, implicitModeValidator, implicitModeProjectId); + + _initialized = true; } // diff --git a/src/tokens/ERC721/presets/items/ERC721Items.sol b/src/tokens/ERC721/presets/items/ERC721Items.sol index e17f124..a311597 100644 --- a/src/tokens/ERC721/presets/items/ERC721Items.sol +++ b/src/tokens/ERC721/presets/items/ERC721Items.sol @@ -11,19 +11,9 @@ contract ERC721Items is ERC721BaseToken, IERC721Items { bytes32 internal constant MINTER_ROLE = keccak256("MINTER_ROLE"); - address private immutable _initializer; - bool private _initialized; - uint256 private _nextSequentialId; uint256 private _totalSupply; - /** - * Deploy contract. - */ - constructor() ERC721BaseToken() { - _initializer = msg.sender; - } - /** * Initialize contract. * @param owner The owner of the contract @@ -48,18 +38,12 @@ contract ERC721Items is ERC721BaseToken, IERC721Items { address implicitModeValidator, bytes32 implicitModeProjectId ) public virtual { - if (msg.sender != _initializer || _initialized) { - revert InvalidInitialization(); - } - ERC721BaseToken._initialize( owner, tokenName, tokenSymbol, tokenBaseURI, tokenContractURI, implicitModeValidator, implicitModeProjectId ); _setDefaultRoyalty(royaltyReceiver, royaltyFeeNumerator); _grantRole(MINTER_ROLE, owner); - - _initialized = true; } // diff --git a/src/tokens/ERC721/presets/soulbound/ERC721Soulbound.sol b/src/tokens/ERC721/presets/soulbound/ERC721Soulbound.sol index 0c43113..b6ef543 100644 --- a/src/tokens/ERC721/presets/soulbound/ERC721Soulbound.sol +++ b/src/tokens/ERC721/presets/soulbound/ERC721Soulbound.sol @@ -13,8 +13,6 @@ contract ERC721Soulbound is ERC721Items, IERC721Soulbound { bool internal _transferLocked; - constructor() ERC721Items() { } - /// @inheritdoc ERC721Items function initialize( address owner, diff --git a/test/_mocks/ERC1155Recipient.sol b/test/_mocks/ERC1155Recipient.sol new file mode 100644 index 0000000..fffa3ce --- /dev/null +++ b/test/_mocks/ERC1155Recipient.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.19; + +import { IERC1155Receiver, IERC165 } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; + +contract ERC1155Recipient is IERC1155Receiver { + + error ExpectedRevert(); + + bool public willRevert; + uint256 public gasUsage; // Roughly how much gas to use in the spin loop + + function setWillRevert( + bool _willRevert + ) public { + willRevert = _willRevert; + } + + function setGasUsage( + uint256 _gasUsage + ) public { + gasUsage = _gasUsage; + } + + function onERC1155Received( + address, + address, + uint256, + uint256, + bytes memory + ) public virtual override returns (bytes4) { + uint256 gasStart = gasleft(); + if (willRevert) { + revert ExpectedRevert(); + } + while (gasStart - gasleft() < gasUsage) { + // Spin + // solhint-disable-next-line no-unused-vars + uint256 a = uint256(0) / uint256(0); + } + return this.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] memory, + uint256[] memory, + bytes memory + ) public virtual override returns (bytes4) { + uint256 gasStart = gasleft(); + if (willRevert) { + revert ExpectedRevert(); + } + while (gasStart - gasleft() < gasUsage) { + // Spin + // solhint-disable-next-line no-unused-vars + uint256 a = uint256(0) / uint256(0); + } + return this.onERC1155BatchReceived.selector; + } + + function supportsInterface( + bytes4 interfaceId + ) public view virtual override returns (bool) { + return interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC165).interfaceId; + } + +} diff --git a/test/tokens/ERC1155/presets/ERC1155Pack.t.sol b/test/tokens/ERC1155/presets/ERC1155Pack.t.sol index dff67f6..110d148 100644 --- a/test/tokens/ERC1155/presets/ERC1155Pack.t.sol +++ b/test/tokens/ERC1155/presets/ERC1155Pack.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.19; import { TestHelper } from "../../../TestHelper.sol"; +import { ERC1155Recipient } from "../../../_mocks/ERC1155Recipient.sol"; import { PackReentryMock } from "../../../_mocks/PackReentryMock.sol"; import { ERC1155Items } from "src/tokens/ERC1155/presets/items/ERC1155Items.sol"; @@ -10,6 +11,7 @@ import { IERC1155ItemsFunctions, IERC1155ItemsSignals } from "src/tokens/ERC1155 import { ERC1155Pack } from "src/tokens/ERC1155/presets/pack/ERC1155Pack.sol"; import { ERC1155PackFactory } from "src/tokens/ERC1155/presets/pack/ERC1155PackFactory.sol"; import { IERC1155Pack } from "src/tokens/ERC1155/presets/pack/IERC1155Pack.sol"; +import { ERC1155Holder } from "src/tokens/ERC1155/utility/holder/ERC1155Holder.sol"; import { ERC721Items } from "src/tokens/ERC721/presets/items/ERC721Items.sol"; import { IERC1155 } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol"; @@ -22,6 +24,10 @@ import { ERC1155 } from "solady/tokens/ERC1155.sol"; contract ERC1155PackHack is ERC1155Pack { + constructor( + address _erc1155Holder + ) ERC1155Pack(_erc1155Holder) { } + function setAllExceptOneClaimed( uint256 _idx ) public { @@ -42,6 +48,7 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { ERC1155Items private token2; ERC721Items private token721; PackReentryMock private reentryAttacker; + ERC1155Holder private holder; address private proxyOwner; address private owner; @@ -66,7 +73,8 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { address(this), "test721", "test721", "ipfs://", "ipfs://", address(this), 0, address(0), bytes32(0) ); - ERC1155PackFactory factory = new ERC1155PackFactory(address(this)); + holder = new ERC1155Holder(); + ERC1155PackFactory factory = new ERC1155PackFactory(address(this), address(holder)); _preparePacksContent(); (bytes32 root,) = TestHelper.getMerklePartsPacks(packsContent, 0); @@ -175,13 +183,15 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { } function testFactoryDetermineAddress( + address holderFallback, + address factoryOwner, TestFactoryDetermineAddressParams memory params ) public { vm.assume(params.proxyOwner != address(0)); vm.assume(params.tokenOwner != address(0)); vm.assume(params.royaltyReceiver != address(0)); params.royaltyFeeNumerator = uint96(bound(params.royaltyFeeNumerator, 0, 10_000)); - ERC1155PackFactory factory = new ERC1155PackFactory(address(this)); + ERC1155PackFactory factory = new ERC1155PackFactory(factoryOwner, holderFallback); address deployedAddr = factory.deploy( params.proxyOwner, params.tokenOwner, @@ -288,7 +298,7 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { vm.assertLt(_getRevealIdx(user), pack.supply(0)); } - function testRevealSuccess( + function testRevealSuccessToUser( address user ) public { assumeSafeAddress(user); @@ -298,6 +308,7 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { IERC1155Pack.PackContent memory packContent = packsContent[revealIdx]; + vm.prank(user); pack.reveal(user, packContent, proof, 0); for (uint256 i = 0; i < packContent.tokenAddresses.length; i++) { @@ -314,6 +325,60 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { } } + function testRevealSuccessToHolder(address user, address sender) public { + assumeSafeAddress(user); + vm.assume(sender != user); + uint256 revealIdx = _getRevealIdx(user); + + (, bytes32[] memory proof) = TestHelper.getMerklePartsPacks(packsContent, revealIdx); + + IERC1155Pack.PackContent memory packContent = packsContent[revealIdx]; + + vm.prank(sender); + pack.reveal(user, packContent, proof, 0); + + for (uint256 i = 0; i < packContent.tokenAddresses.length; i++) { + for (uint256 j = 0; j < packContent.tokenIds[i].length; j++) { + if (packContent.isERC721[i]) { + // To user + vm.assertEq(IERC721(packContent.tokenAddresses[i]).ownerOf(packContent.tokenIds[i][j]), user); + } else { + // To holder with claim + vm.assertEq( + IERC1155(packContent.tokenAddresses[i]).balanceOf(address(holder), packContent.tokenIds[i][j]), + packContent.amounts[i][j] + ); + vm.assertEq( + holder.claims(user, packContent.tokenAddresses[i], packContent.tokenIds[i][j]), + packContent.amounts[i][j] + ); + } + } + } + + // After reveal, sender can claim tokens on behalf of user. + // In pactice, this will be batched with revertOnError: false + for (uint256 i = 0; i < packContent.tokenAddresses.length; i++) { + if (!packContent.isERC721[i]) { + vm.prank(sender); + holder.claimBatch(user, packContent.tokenAddresses[i], packContent.tokenIds[i]); + } + } + + for (uint256 i = 0; i < packContent.tokenAddresses.length; i++) { + if (!packContent.isERC721[i]) { + for (uint256 j = 0; j < packContent.tokenIds[i].length; j++) { + // User now holds tokens + vm.assertEq( + IERC1155(packContent.tokenAddresses[i]).balanceOf(user, packContent.tokenIds[i][j]), + packContent.amounts[i][j] + ); + vm.assertEq(holder.claims(user, packContent.tokenAddresses[i], packContent.tokenIds[i][j]), 0); + } + } + } + } + function testFinalRevealSuccess(address user, uint256 size, uint256 unclaimedIdx) public { assumeSafeAddress(user); size = bound(size, 2, 1000); //FIXME 10000 @@ -323,7 +388,7 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { packsContent = new IERC1155Pack.PackContent[](size); (bytes32 root,) = TestHelper.getMerklePartsPacks(packsContent, 0); - ERC1155PackHack packHack = new ERC1155PackHack(); + ERC1155PackHack packHack = new ERC1155PackHack(address(holder)); packHack.initialize(owner, "name", "baseURI", "contractURI", address(this), 0, address(0), bytes32(0)); vm.prank(owner); @@ -349,7 +414,12 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { IERC1155Pack.PackContent memory packContent = packsContent[unclaimedIdx]; pack.reveal(user, packContent, proof, 0); - vm.assertEq(token.balanceOf(user, 1), 0); + // Validate amounts sent + for (uint256 i = 0; i < packContent.tokenAddresses.length; i++) { + for (uint256 j = 0; j < packContent.tokenIds[i].length; j++) { + vm.assertEq(token.balanceOf(user, packContent.tokenIds[i][j]), packContent.amounts[i][j]); + } + } } function testRevealInvalidPackContent( @@ -425,8 +495,41 @@ contract ERC1155PackTest is TestHelper, IERC1155ItemsSignals { reentryAttacker.setPackAndProof(proof, packContent); - vm.expectRevert(IERC1155Pack.NoCommit.selector); + for (uint256 i = 0; i < packContent.tokenAddresses.length; i++) { + if (packContent.isERC721[i]) { + continue; + } + uint256[] memory tokenIds = packContent.tokenIds[i]; + uint256[] memory amounts = packContent.amounts[i]; + vm.expectEmit(true, true, true, true); + emit ERC1155Holder.ClaimAddedBatch( + address(reentryAttacker), address(packContent.tokenAddresses[i]), tokenIds, amounts + ); + } + vm.expectEmit(true, true, true, true); + emit IERC1155Pack.Reveal(address(reentryAttacker), 0); pack.reveal(address(reentryAttacker), packContent, proof, 0); + + // Error caught and tokens stored in holder + for (uint256 i = 0; i < packContent.tokenAddresses.length; i++) { + if (packContent.isERC721[i]) { + continue; + } + uint256[] memory tokenIds = packContent.tokenIds[i]; + uint256[] memory amounts = packContent.amounts[i]; + for (uint256 j = 0; j < tokenIds.length; j++) { + vm.assertEq( + IERC1155(address(packContent.tokenAddresses[i])).balanceOf(address(reentryAttacker), tokenIds[j]), 0 + ); + vm.assertEq( + IERC1155(address(packContent.tokenAddresses[i])).balanceOf(address(holder), tokenIds[j]), amounts[j] + ); + vm.assertEq( + holder.claims(address(reentryAttacker), address(packContent.tokenAddresses[i]), tokenIds[j]), + amounts[j] + ); + } + } } function testCantRefundAfterReveal( diff --git a/test/tokens/ERC1155/utility/holder/ERC1155Holder.t.sol b/test/tokens/ERC1155/utility/holder/ERC1155Holder.t.sol new file mode 100644 index 0000000..3860eb5 --- /dev/null +++ b/test/tokens/ERC1155/utility/holder/ERC1155Holder.t.sol @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.19; + +import { TestHelper } from "test/TestHelper.sol"; +import { ERC1155Recipient } from "test/_mocks/ERC1155Recipient.sol"; + +import { ERC1155Items } from "src/tokens/ERC1155/presets/items/ERC1155Items.sol"; +import { ERC1155Holder } from "src/tokens/ERC1155/utility/holder/ERC1155Holder.sol"; + +import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155/IERC1155Receiver.sol"; +import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; + +import { ERC1155 } from "solady/tokens/ERC1155.sol"; + +contract ERC1155HolderTest is TestHelper { + + // Redeclare events + event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); + event ClaimAdded(address claimant, address tokenAddress, uint256 tokenId, uint256 amount); + event ClaimAddedBatch(address claimant, address tokenAddress, uint256[] tokenIds, uint256[] amounts); + event Claimed(address claimant, address tokenAddress, uint256 tokenId, uint256 amount); + event ClaimedBatch(address claimant, address tokenAddress, uint256[] tokenIds, uint256[] amounts); + + ERC1155Items private _token; + ERC1155Items private _token2; + ERC1155Holder private _holder; + ERC1155Recipient private _recipient; + + function setUp() public { + vm.deal(address(this), 100 ether); + + _token = new ERC1155Items(); + _token.initialize(address(this), "test", "ipfs://", "ipfs://", address(this), 0, address(0), bytes32(0)); + + _token2 = new ERC1155Items(); + _token2.initialize(address(this), "test2", "ipfs://", "ipfs://", address(this), 0, address(0), bytes32(0)); + + _holder = new ERC1155Holder(); + _recipient = new ERC1155Recipient(); + } + + function testSupportsInterface() public view { + assertTrue(_holder.supportsInterface(type(IERC165).interfaceId)); + assertTrue(_holder.supportsInterface(type(IERC1155Receiver).interfaceId)); + } + + function testRecipientGasUsage(address operator, address from, uint256 tokenId, uint256 amount) public { + _recipient.onERC1155Received(operator, from, tokenId, amount, ""); + } + + function testRecipientGasUsageBatch( + address operator, + address from, + uint256[] memory tokenIds, + uint256[] memory amounts + ) public { + _recipient.onERC1155BatchReceived(operator, from, tokenIds, amounts, ""); + } + + function testTransferAddsClaimForClaimant( + address sender, + address claimant, + uint256 tokenId, + uint256 amount, + bool tightPacked + ) public returns (address, address, uint256, uint256) { + assumeUnusedAddress(sender); + if (claimant != address(_recipient)) { + assumeUnusedAddress(claimant); + } + amount = bound(amount, 1, 1000); + + // Mint tokens to sender first + _token.mint(address(sender), tokenId, amount, ""); + + // Transfer tokens to holder with claimant data + bytes memory claimData = tightPacked ? abi.encodePacked(claimant) : abi.encode(claimant); + vm.expectEmit(true, true, true, true); + emit ClaimAdded(claimant, address(_token), tokenId, amount); + vm.prank(sender); + _token.safeTransferFrom(address(sender), address(_holder), tokenId, amount, claimData); + + // Verify holder holds the tokens + assertEq(_token.balanceOf(claimant, tokenId), 0); + assertEq(_token.balanceOf(address(_holder), tokenId), amount); + + // Verify claim was added + assertEq(_holder.claims(claimant, address(_token), tokenId), amount); + + return (sender, claimant, tokenId, amount); + } + + function testTransferAddsClaimForClaimantBatch( + address sender, + address claimant, + uint256[] memory tokenIds, + uint256[] memory amounts, + bool tightPacked + ) public returns (address, address, uint256[] memory, uint256[] memory) { + assumeUnusedAddress(sender); + if (claimant != address(_recipient)) { + assumeUnusedAddress(claimant); + } + vm.assume(tokenIds.length > 0); + uint256 tokenIdsLength = tokenIds.length > 10 ? 10 : tokenIds.length; + vm.assume(amounts.length >= tokenIdsLength); + assembly { + // Fix array lengths + mstore(tokenIds, tokenIdsLength) + mstore(amounts, tokenIdsLength) + } + assumeNoDuplicates(tokenIds); + + for (uint256 i = 0; i < tokenIds.length; i++) { + amounts[i] = bound(amounts[i], 1, 1000); + // Mint tokens to sender first + _token.mint(address(sender), tokenIds[i], amounts[i], ""); + } + + bytes memory claimData = tightPacked ? abi.encodePacked(claimant) : abi.encode(claimant); + vm.expectEmit(true, true, true, true); + emit ClaimAddedBatch(claimant, address(_token), tokenIds, amounts); + vm.prank(sender); + _token.safeBatchTransferFrom(address(sender), address(_holder), tokenIds, amounts, claimData); + + // Verify holder holds the tokens + for (uint256 i = 0; i < tokenIds.length; i++) { + assertEq(_token.balanceOf(claimant, tokenIds[i]), 0); + assertEq(_token.balanceOf(address(_holder), tokenIds[i]), amounts[i]); + // Verify claim was added + assertEq(_holder.claims(claimant, address(_token), tokenIds[i]), amounts[i]); + } + + return (sender, claimant, tokenIds, amounts); + } + + function testClaimSingleTokenToEOA( + address sender, + address claimant, + uint256 tokenId, + uint256 amount, + bool tightPacked + ) public { + (sender, claimant, tokenId, amount) = + testTransferAddsClaimForClaimant(sender, claimant, tokenId, amount, tightPacked); + + // Execute claim + vm.expectEmit(true, true, true, true); + emit Claimed(claimant, address(_token), tokenId, amount); + _holder.claim(claimant, address(_token), tokenId); + + // Verify tokens transferred + assertEq(_token.balanceOf(claimant, tokenId), amount); + assertEq(_token.balanceOf(address(_holder), tokenId), 0); + + // Verify claim cleared + assertEq(_holder.claims(claimant, address(_token), tokenId), 0); + } + + function testClaimSingleTokenToRecipient( + address sender, + uint256 tokenId, + uint256 amount, + bool tightPacked + ) public { + (sender,, tokenId, amount) = + testTransferAddsClaimForClaimant(sender, address(_recipient), tokenId, amount, tightPacked); + + // Execute claim + vm.expectEmit(true, true, true, true); + emit Claimed(address(_recipient), address(_token), tokenId, amount); + _holder.claim(address(_recipient), address(_token), tokenId); + + // Verify tokens transferred + assertEq(_token.balanceOf(address(_recipient), tokenId), amount); + assertEq(_token.balanceOf(address(_holder), tokenId), 0); + + // Verify claim cleared + assertEq(_holder.claims(address(_recipient), address(_token), tokenId), 0); + } + + function testClaimBatchTokensToEOA( + address sender, + address claimant, + uint256[] memory tokenIds, + uint256[] memory amounts, + bool tightPacked + ) public { + (sender, claimant, tokenIds, amounts) = + testTransferAddsClaimForClaimantBatch(sender, claimant, tokenIds, amounts, tightPacked); + + // Test claim batch event + vm.expectEmit(true, true, true, true); + emit ClaimedBatch(claimant, address(_token), tokenIds, amounts); + _holder.claimBatch(claimant, address(_token), tokenIds); + + // Verify tokens transferred + for (uint256 i = 0; i < tokenIds.length; i++) { + assertEq(_token.balanceOf(claimant, tokenIds[i]), amounts[i]); + assertEq(_token.balanceOf(address(_holder), tokenIds[i]), 0); + // Verify claim cleared + assertEq(_holder.claims(claimant, address(_token), tokenIds[i]), 0); + } + } + + function testClaimBatchTokensToRecipient( + address sender, + uint256[] memory tokenIds, + uint256[] memory amounts, + bool tightPacked + ) public { + (sender,, tokenIds, amounts) = + testTransferAddsClaimForClaimantBatch(sender, address(_recipient), tokenIds, amounts, tightPacked); + + // Test claim batch event + vm.expectEmit(true, true, true, true); + emit ClaimedBatch(address(_recipient), address(_token), tokenIds, amounts); + _holder.claimBatch(address(_recipient), address(_token), tokenIds); + + // Verify tokens transferred + for (uint256 i = 0; i < tokenIds.length; i++) { + assertEq(_token.balanceOf(address(_recipient), tokenIds[i]), amounts[i]); + assertEq(_token.balanceOf(address(_holder), tokenIds[i]), 0); + // Verify claim cleared + assertEq(_holder.claims(address(_recipient), address(_token), tokenIds[i]), 0); + } + } + + function testClaimantDecodingAddressZero( + bool tightPacked + ) public { + // Address 0 + bytes memory claimData = tightPacked ? abi.encodePacked(address(0)) : abi.encode(address(0)); + vm.expectRevert(ERC1155Holder.InvalidClaimant.selector); + _holder.onERC1155Received(address(0), address(_token), 0, 0, claimData); + vm.expectRevert(ERC1155Holder.InvalidClaimant.selector); + _holder.onERC1155BatchReceived(address(0), address(_token), new uint256[](1), new uint256[](1), claimData); + } + + function testClaimantDecodingInvalidData( + bytes memory claimData + ) public { + vm.assume(claimData.length != 20 && claimData.length != 32); + vm.expectRevert(ERC1155Holder.InvalidClaimant.selector); + _holder.onERC1155Received(address(0), address(_token), 0, 0, claimData); + vm.expectRevert(ERC1155Holder.InvalidClaimant.selector); + _holder.onERC1155BatchReceived(address(0), address(_token), new uint256[](1), new uint256[](1), claimData); + } + +}