diff --git a/.gas-snapshot b/.gas-snapshot index 2cecb0d6..e1911683 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,8 +1,502 @@ BundleRegistryGasUsageTest:testGasRegisterWithSig() (gas: 1118748) +BundlerTest:testFuzzRegister(address,uint256,address,uint256,uint8,uint40) (runs: 519, μ: 938144, ~: 822489) +BundlerTest:testFuzzRegisterReturnsExcessPayment(address,uint256,address,uint40,uint256,uint256) (runs: 519, μ: 293476, ~: 293847) +BundlerTest:testFuzzRegisterRevertsInsufficientPayment(address,uint256,address,uint40,uint256,uint256) (runs: 519, μ: 219464, ~: 219543) +BundlerTest:testFuzzRegisterZeroStorage(address,uint256,address,uint8,uint40) (runs: 519, μ: 955365, ~: 819877) +BundlerTest:testFuzzRevertsDirectPayments(address,uint256) (runs: 519, μ: 19429, ~: 19481) +BundlerTest:testHasIDRegistry() (gas: 7633) +BundlerTest:testVersion() (gas: 6872) +EIP712Test:testExposesDomainSeparator() (gas: 5521) +FnameResolverTest:testFuzzInterfaceDetectionUnsupportedInterface(bytes4) (runs: 519, μ: 8701, ~: 8701) +FnameResolverTest:testFuzzOnlyOwnerCanAddSigner(address,address) (runs: 519, μ: 13744, ~: 13744) +FnameResolverTest:testFuzzOnlyOwnerCanRemoveSigner(address,address) (runs: 519, μ: 13646, ~: 13646) +FnameResolverTest:testFuzzOwnerCanAddSigner(address) (runs: 519, μ: 38739, ~: 38739) +FnameResolverTest:testFuzzOwnerCanRemoveSigner(address) (runs: 519, μ: 29892, ~: 29878) +FnameResolverTest:testFuzzResolveRevertsNonAddrFunction(bytes,bytes) (runs: 519, μ: 12894, ~: 12836) +FnameResolverTest:testFuzzResolveRevertsWithOffchainLookup(bytes,bytes) (runs: 519, μ: 28752, ~: 28356) +FnameResolverTest:testFuzzResolveWithProofInvalidName(string,uint256,address) (runs: 519, μ: 26190, ~: 26067) +FnameResolverTest:testFuzzResolveWithProofInvalidOwner(string,uint256,address) (runs: 519, μ: 25898, ~: 25815) +FnameResolverTest:testFuzzResolveWithProofInvalidSignerLength(string,uint256,address,bytes,uint8) (runs: 513, μ: 19993, ~: 19932) +FnameResolverTest:testFuzzResolveWithProofInvalidTimestamp(string,uint256,address) (runs: 519, μ: 25899, ~: 25816) +FnameResolverTest:testFuzzResolveWithProofValidSignature(string,uint256,address) (runs: 519, μ: 33970, ~: 33886) +FnameResolverTest:testFuzzResolveWithProofWrongSigner(string,uint256,address) (runs: 519, μ: 25815, ~: 25732) +FnameResolverTest:testInitialOwner() (gas: 9747) +FnameResolverTest:testInterfaceDetectionERC165() (gas: 5692) +FnameResolverTest:testInterfaceDetectionIExtendedResolver() (gas: 5653) +FnameResolverTest:testProofTypehash() (gas: 5509) +FnameResolverTest:testSignerIsAuthorized() (gas: 9919) +FnameResolverTest:testURL() (gas: 14324) +FnameResolverTest:testVersion() (gas: 7069) IdGatewayGasUsageTest:testGasRegister() (gas: 1402640) IdGatewayGasUsageTest:testGasRegisterForAndRecover() (gas: 1973946) +IdGatewayOwnerTest:testFuzzAcceptOwnership(address) (runs: 519, μ: 33378, ~: 33364) +IdGatewayOwnerTest:testFuzzCannotAcceptOwnershipUnlessPendingOwner(address,address) (runs: 519, μ: 41351, ~: 41351) +IdGatewayOwnerTest:testFuzzCannotPauseUnlessGuardian(address) (runs: 519, μ: 20659, ~: 20659) +IdGatewayOwnerTest:testFuzzCannotTransferOwnershipUnlessOwner(address,address) (runs: 519, μ: 19851, ~: 19851) +IdGatewayOwnerTest:testFuzzCannotUnpauseUnlessOwner(address) (runs: 519, μ: 42111, ~: 42111) +IdGatewayOwnerTest:testFuzzTransferOwnership(address,address) (runs: 519, μ: 46578, ~: 46578) +IdGatewayOwnerTest:testPause() (gas: 39786) +IdGatewayOwnerTest:testUnpause() (gas: 28920) +IdGatewayTest:testFuzzCannotRegisterForIfPaused(address,uint256,address,uint40) (runs: 519, μ: 68685, ~: 68668) +IdGatewayTest:testFuzzCannotRegisterForToAnAddressThatOwnsAnId(address,uint256,address,uint40) (runs: 519, μ: 139288, ~: 139271) +IdGatewayTest:testFuzzCannotRegisterIfPaused(address,address) (runs: 519, μ: 56439, ~: 56439) +IdGatewayTest:testFuzzCannotRegisterToAnAddressThatOwnsAnId(address,address) (runs: 519, μ: 128103, ~: 128103) +IdGatewayTest:testFuzzOnlyOwnerCanSetStorageRegistry(address,address) (runs: 519, μ: 17622, ~: 17622) +IdGatewayTest:testFuzzRegister(address,address) (runs: 519, μ: 189882, ~: 189959) +IdGatewayTest:testFuzzRegisterExtraStorage(address,address,uint16) (runs: 519, μ: 190197, ~: 190313) +IdGatewayTest:testFuzzRegisterFor(address,uint256,address,uint40) (runs: 519, μ: 226709, ~: 226923) +IdGatewayTest:testFuzzRegisterForERC1271(address,uint256,address,uint40) (runs: 519, μ: 718477, ~: 718691) +IdGatewayTest:testFuzzRegisterForExtraStorage(address,uint256,address,uint40,uint16) (runs: 519, μ: 227125, ~: 227261) +IdGatewayTest:testFuzzRegisterForRevertsBadSig(address,uint256,address,uint40) (runs: 519, μ: 66650, ~: 66633) +IdGatewayTest:testFuzzRegisterForRevertsExpiredSig(address,uint256,address,uint40) (runs: 519, μ: 63328, ~: 63311) +IdGatewayTest:testFuzzRegisterForRevertsInvalidSig(address,uint256,address,uint40) (runs: 519, μ: 70728, ~: 70711) +IdGatewayTest:testFuzzRegisterForRevertsMaliciousERC1271(address,uint256,address,uint40) (runs: 519, μ: 596604, ~: 596587) +IdGatewayTest:testFuzzRegisterForRevertsUsedNonce(address,uint256,address,uint40) (runs: 519, μ: 71985, ~: 71968) +IdGatewayTest:testFuzzRegisterReturnsOverpayment(address,address,uint32) (runs: 519, μ: 227488, ~: 229291) +IdGatewayTest:testFuzzRevertsDirectPayments(address,uint256) (runs: 519, μ: 23996, ~: 24035) +IdGatewayTest:testFuzzSetStorageRegistry(address) (runs: 519, μ: 22845, ~: 22873) +IdGatewayTest:testIdRegistry() (gas: 7677) +IdGatewayTest:testRegisterTypehash() (gas: 5530) +IdGatewayTest:testStorageRegistry() (gas: 9786) +IdGatewayTest:testVersion() (gas: 7044) +IdRegistryOwnerTest:testAddRemoveGuardian(address) (runs: 519, μ: 32200, ~: 32186) +IdRegistryOwnerTest:testCannotAddGuardianUnlessOwner(address,address) (runs: 519, μ: 18144, ~: 18144) +IdRegistryOwnerTest:testCannotRemoveGuardianUnlessOwner(address,address) (runs: 519, μ: 18166, ~: 18166) +IdRegistryOwnerTest:testFuzzAcceptOwnership(address) (runs: 519, μ: 33388, ~: 33374) +IdRegistryOwnerTest:testFuzzCannotAcceptOwnershipUnlessPendingOwner(address,address) (runs: 519, μ: 41385, ~: 41385) +IdRegistryOwnerTest:testFuzzCannotPauseUnlessGuardian(address) (runs: 519, μ: 20704, ~: 20704) +IdRegistryOwnerTest:testFuzzCannotTransferOwnershipUnlessOwner(address,address) (runs: 519, μ: 19875, ~: 19875) +IdRegistryOwnerTest:testFuzzCannotUnpauseUnlessOwner(address) (runs: 519, μ: 41336, ~: 41336) +IdRegistryOwnerTest:testFuzzTransferOwnership(address,address) (runs: 519, μ: 46592, ~: 46592) +IdRegistryOwnerTest:testPause() (gas: 38990) +IdRegistryOwnerTest:testUnpause() (gas: 28325) +IdRegistryTest:testBulkRegisterCannotReRegister() (gas: 231216) +IdRegistryTest:testBulkRegisterEmitsEvent() (gas: 235228) +IdRegistryTest:testBulkRegisterUnpausedReverts() (gas: 25513) +IdRegistryTest:testBulkRegisterWithRecoveryCannotReRegister(address) (runs: 519, μ: 229491, ~: 229722) +IdRegistryTest:testBulkRegisterWithRecoveryEmitsEvent(address) (runs: 519, μ: 233367, ~: 233598) +IdRegistryTest:testBulkRegisterWithRecoveryUnpausedReverts(address) (runs: 519, μ: 24407, ~: 24407) +IdRegistryTest:testBulkResetEmitsEvent() (gas: 189812) +IdRegistryTest:testFreezeIdGatewayRevertsWhenFrozen() (gas: 38903) +IdRegistryTest:testFuzzBulkRegisterAfterGracePeriodRevertsUnauthorized(uint40) (runs: 519, μ: 31121, ~: 31073) +IdRegistryTest:testFuzzBulkRegisterDuringGracePeriod(uint40) (runs: 519, μ: 98488, ~: 98194) +IdRegistryTest:testFuzzBulkRegisterIds(uint24[],uint128,uint128) (runs: 518, μ: 3348158, ~: 2994716) +IdRegistryTest:testFuzzBulkRegisterIdsWithRecovery(uint24[],uint128,address) (runs: 518, μ: 3397485, ~: 3071786) +IdRegistryTest:testFuzzBulkRegisterWithRecoveryAfterGracePeriodRevertsUnauthorized(uint40,address) (runs: 519, μ: 30938, ~: 30895) +IdRegistryTest:testFuzzBulkRegisterWithRecoveryDuringGracePeriod(uint40,address) (runs: 519, μ: 98132, ~: 97819) +IdRegistryTest:testFuzzBulkResetAfterGracePeriodRevertsUnauthorized(uint40) (runs: 519, μ: 30077, ~: 30029) +IdRegistryTest:testFuzzBulkResetDuringGracePeriod(uint40) (runs: 519, μ: 195884, ~: 195652) +IdRegistryTest:testFuzzBulkResetIds(uint24[]) (runs: 518, μ: 3080497, ~: 2648233) +IdRegistryTest:testFuzzBulkResetUnpausedReverts() (gas: 20842) +IdRegistryTest:testFuzzCannotChangeRecoveryAddressForWhenPaused(address,uint256,address,address,uint40) (runs: 519, μ: 147957, ~: 148005) +IdRegistryTest:testFuzzCannotChangeRecoveryAddressForWithoutId(address,uint256,address,address,uint40) (runs: 519, μ: 26873, ~: 26845) +IdRegistryTest:testFuzzCannotChangeRecoveryAddressWhenPaused(address,address,address) (runs: 519, μ: 136013, ~: 136129) +IdRegistryTest:testFuzzCannotChangeRecoveryAddressWithoutId(address,address) (runs: 519, μ: 13822, ~: 13822) +IdRegistryTest:testFuzzCannotMigrateTwice(uint40) (runs: 519, μ: 28663, ~: 28651) +IdRegistryTest:testFuzzCannotRecoverForFromAddressWithNoId(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 46035, ~: 46002) +IdRegistryTest:testFuzzCannotRecoverForToAddressWithId(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 194212, ~: 194256) +IdRegistryTest:testFuzzCannotRecoverToAddressThatOwnsAnId(address,uint256,uint40,address) (runs: 519, μ: 185843, ~: 185943) +IdRegistryTest:testFuzzCannotRecoverUnlessRecoveryAddress(address,uint256,uint40,address,address) (runs: 519, μ: 132015, ~: 132073) +IdRegistryTest:testFuzzCannotRecoverWhenPaused(address,uint256,uint40,address) (runs: 519, μ: 186297, ~: 186397) +IdRegistryTest:testFuzzCannotRecoverWithoutId(address,uint256,uint40,address) (runs: 519, μ: 35629, ~: 35614) +IdRegistryTest:testFuzzCannotRegisterIfPaused(address,address) (runs: 519, μ: 60669, ~: 60669) +IdRegistryTest:testFuzzCannotRegisterToAnAddressThatOwnsAnId(address,address) (runs: 519, μ: 98605, ~: 98644) +IdRegistryTest:testFuzzCannotTransferAndChangeRecoveryForToAddressWithId(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 171959, ~: 171926) +IdRegistryTest:testFuzzCannotTransferAndChangeRecoveryIfNoId(address,address,uint256,uint40) (runs: 519, μ: 43482, ~: 43469) +IdRegistryTest:testFuzzCannotTransferAndChangeRecoveryWhenPaused(address,address,uint256,uint40) (runs: 519, μ: 166347, ~: 166411) +IdRegistryTest:testFuzzCannotTransferAndChangeToAddressWithId(address,uint256,uint40,address,address) (runs: 519, μ: 202737, ~: 202948) +IdRegistryTest:testFuzzCannotTransferForFromAddressWithNoId(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 50609, ~: 50576) +IdRegistryTest:testFuzzCannotTransferForFromAddressWithNoId(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 50393, ~: 50353) +IdRegistryTest:testFuzzCannotTransferForToAddressWithId(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 171608, ~: 171568) +IdRegistryTest:testFuzzCannotTransferIfNoId(address,uint256,uint40) (runs: 519, μ: 38879, ~: 38860) +IdRegistryTest:testFuzzCannotTransferToAddressWithId(address,uint256,uint40,address) (runs: 519, μ: 200126, ~: 200265) +IdRegistryTest:testFuzzCannotTransferWhenPaused(address,uint256,uint40) (runs: 519, μ: 163606, ~: 163702) +IdRegistryTest:testFuzzCannotVerifyFidSignatureERC1271IfBadCustodyAddress(uint256,bytes32) (runs: 519, μ: 575466, ~: 575451) +IdRegistryTest:testFuzzCannotVerifyFidSignatureERC1271IfBadDigest(uint256,bytes32,bytes32) (runs: 519, μ: 588045, ~: 588028) +IdRegistryTest:testFuzzCannotVerifyFidSignatureERC1271IfMalicious(uint256,bytes32) (runs: 519, μ: 626926, ~: 626911) +IdRegistryTest:testFuzzCannotVerifyFidSignatureIfBadCustodyAddress(uint256,bytes32,address) (runs: 519, μ: 95518, ~: 95497) +IdRegistryTest:testFuzzCannotVerifyFidSignatureIfBadDigest(uint256,bytes32,bytes32) (runs: 519, μ: 101373, ~: 101356) +IdRegistryTest:testFuzzCannotVerifyFidSignatureIfBadFid(uint256,bytes32) (runs: 519, μ: 93014, ~: 92999) +IdRegistryTest:testFuzzChangeRecoveryAddress(address,address,address) (runs: 519, μ: 111475, ~: 111629) +IdRegistryTest:testFuzzChangeRecoveryAddressFor(address,uint256,address,address,uint40) (runs: 519, μ: 149890, ~: 149938) +IdRegistryTest:testFuzzChangeRecoveryAddressForRevertsBadSig(address,uint256,address,address,uint40) (runs: 519, μ: 146140, ~: 146188) +IdRegistryTest:testFuzzChangeRecoveryAddressForRevertsExpired(address,uint256,address,address,uint40) (runs: 519, μ: 142988, ~: 143036) +IdRegistryTest:testFuzzChangeRecoveryAddressForRevertsInvalidSig(address,uint256,address,address,uint40) (runs: 519, μ: 150422, ~: 150470) +IdRegistryTest:testFuzzChangeRecoveryAddressForRevertsUsedNonce(address,uint256,address,address,uint40) (runs: 519, μ: 151748, ~: 151796) +IdRegistryTest:testFuzzFreezeIdGateway(address) (runs: 519, μ: 42921, ~: 42921) +IdRegistryTest:testFuzzMigration(uint40) (runs: 518, μ: 23329, ~: 23329) +IdRegistryTest:testFuzzOnlyMigratorCanMigrate(address) (runs: 519, μ: 17351, ~: 17351) +IdRegistryTest:testFuzzOnlyOwnerCanFreezeIdGateway(address) (runs: 519, μ: 13578, ~: 13578) +IdRegistryTest:testFuzzOnlyOwnerCanSetIdGateway(address,address) (runs: 519, μ: 13836, ~: 13836) +IdRegistryTest:testFuzzOwnerCanSetMigrator(address) (runs: 519, μ: 25158, ~: 25177) +IdRegistryTest:testFuzzRecover(address,uint256,uint40,address) (runs: 519, μ: 165316, ~: 165340) +IdRegistryTest:testFuzzRecoverFor(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 202772, ~: 202739) +IdRegistryTest:testFuzzRecoverForForRevertsInvalidToSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 195561, ~: 195605) +IdRegistryTest:testFuzzRecoverForForRevertsUsedRecoveryNonce(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 172154, ~: 172198) +IdRegistryTest:testFuzzRecoverForForRevertsUsedToNonce(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 196954, ~: 196998) +IdRegistryTest:testFuzzRecoverForRevertsInvalidRecoverySig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 170812, ~: 170856) +IdRegistryTest:testFuzzRecoverForRevertsWhenPaused(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 220482, ~: 220526) +IdRegistryTest:testFuzzRecoverRevertsBadSig(address,uint256,uint40,address) (runs: 519, μ: 155657, ~: 155757) +IdRegistryTest:testFuzzRecoverRevertsExpiredSig(address,uint256,uint40,address) (runs: 519, μ: 152445, ~: 152545) +IdRegistryTest:testFuzzRecoverRevertsInvalidSig(address,uint256,uint40,address) (runs: 519, μ: 159908, ~: 160008) +IdRegistryTest:testFuzzRegister(address,address) (runs: 519, μ: 116492, ~: 116569) +IdRegistryTest:testFuzzRegisterRevertsUnauthorized(address,address,address) (runs: 519, μ: 33425, ~: 33425) +IdRegistryTest:testFuzzSetIdCounter(uint256) (runs: 519, μ: 41518, ~: 41787) +IdRegistryTest:testFuzzSetIdCounterAfterGracePeriodReverts(uint256,uint40) (runs: 519, μ: 33233, ~: 33196) +IdRegistryTest:testFuzzSetIdCounterDuringGracePeriod(uint256,uint40) (runs: 519, μ: 54221, ~: 54161) +IdRegistryTest:testFuzzSetIdCounterUnpausedReverts(uint256) (runs: 519, μ: 23913, ~: 23913) +IdRegistryTest:testFuzzSetIdGateway(address) (runs: 519, μ: 40342, ~: 40342) +IdRegistryTest:testFuzzSetIdGatewayRevertsWhenFrozen(address) (runs: 519, μ: 40181, ~: 40181) +IdRegistryTest:testFuzzSetMigratorRevertsWhenMigrated(address) (runs: 519, μ: 24910, ~: 24910) +IdRegistryTest:testFuzzSetMigratorRevertsWhenUnpaused(address) (runs: 519, μ: 20134, ~: 20134) +IdRegistryTest:testFuzzTransfer(address,uint256,uint40) (runs: 519, μ: 140424, ~: 140405) +IdRegistryTest:testFuzzTransferAndChangeRecovery(address,address,uint256,uint40) (runs: 519, μ: 166846, ~: 166910) +IdRegistryTest:testFuzzTransferAndChangeRecoveryFor(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 202335, ~: 202379) +IdRegistryTest:testFuzzTransferAndChangeRecoveryForRevertsBadToSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 173685, ~: 173652) +IdRegistryTest:testFuzzTransferAndChangeRecoveryForRevertsExpiredFromSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 145782, ~: 145749) +IdRegistryTest:testFuzzTransferAndChangeRecoveryForRevertsExpiredToSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 157636, ~: 146270) +IdRegistryTest:testFuzzTransferAndChangeRecoveryForRevertsInvalidFromSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 153122, ~: 153089) +IdRegistryTest:testFuzzTransferAndChangeRecoveryForRevertsWhenPaused(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 200940, ~: 200907) +IdRegistryTest:testFuzzTransferAndChangeRecoveryRevertsBadSig(address,address,uint256,uint40) (runs: 519, μ: 138144, ~: 138208) +IdRegistryTest:testFuzzTransferAndChangeRecoveryRevertsExpiredSig(address,address,uint256,uint40) (runs: 519, μ: 134702, ~: 134766) +IdRegistryTest:testFuzzTransferAndChangeRecoveryRevertsInvalidSig(address,address,uint256,uint40) (runs: 519, μ: 142342, ~: 142406) +IdRegistryTest:testFuzzTransferAndChangeRecoverySetsRecovery(address,uint256[10],uint40,address,address[10]) (runs: 519, μ: 706031, ~: 706549) +IdRegistryTest:testFuzzTransferDoesntResetRecovery(address,uint256,uint40,address) (runs: 519, μ: 162630, ~: 162654) +IdRegistryTest:testFuzzTransferFor(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 178148, ~: 178108) +IdRegistryTest:testFuzzTransferForRevertsBadFromSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 148892, ~: 148859) +IdRegistryTest:testFuzzTransferForRevertsBadFromSig(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 146229, ~: 146189) +IdRegistryTest:testFuzzTransferForRevertsBadRecoverySig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 166669, ~: 166713) +IdRegistryTest:testFuzzTransferForRevertsBadToSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 191392, ~: 191436) +IdRegistryTest:testFuzzTransferForRevertsBadToSig(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 170994, ~: 170954) +IdRegistryTest:testFuzzTransferForRevertsExpiredFromSig(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 143070, ~: 143030) +IdRegistryTest:testFuzzTransferForRevertsExpiredRecoverySig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 163475, ~: 163519) +IdRegistryTest:testFuzzTransferForRevertsExpiredToSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 175348, ~: 164082) +IdRegistryTest:testFuzzTransferForRevertsExpiredToSig(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 155445, ~: 167754) +IdRegistryTest:testFuzzTransferForRevertsInvalidFromSig(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 150415, ~: 150375) +IdRegistryTest:testFuzzTransferForRevertsInvalidToSig(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 177920, ~: 177887) +IdRegistryTest:testFuzzTransferForRevertsInvalidToSig(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 175207, ~: 175167) +IdRegistryTest:testFuzzTransferForRevertsUsedFromNonce(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 154493, ~: 154460) +IdRegistryTest:testFuzzTransferForRevertsUsedFromNonce(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 151735, ~: 151695) +IdRegistryTest:testFuzzTransferForRevertsUsedToNonce(address,uint256,uint256,address,uint40,uint40) (runs: 519, μ: 179299, ~: 179266) +IdRegistryTest:testFuzzTransferForRevertsUsedToNonce(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 176556, ~: 176516) +IdRegistryTest:testFuzzTransferForRevertsWhenPaused(address,uint256,uint256,uint40,uint40) (runs: 519, μ: 198133, ~: 198093) +IdRegistryTest:testFuzzTransferReregister(address,uint256,uint40) (runs: 519, μ: 191802, ~: 191898) +IdRegistryTest:testFuzzTransferRevertsBadSig(address,uint256,uint40) (runs: 519, μ: 135413, ~: 135509) +IdRegistryTest:testFuzzTransferRevertsExpiredSig(address,uint256,uint40) (runs: 519, μ: 132166, ~: 132262) +IdRegistryTest:testFuzzTransferRevertsInvalidSig(address,uint256,uint40) (runs: 519, μ: 139666, ~: 139762) +IdRegistryTest:testFuzzVerifyFidSignature(uint256,bytes32) (runs: 519, μ: 96914, ~: 96899) +IdRegistryTest:testFuzzVerifyFidSignatureERC1271(uint256,bytes32) (runs: 519, μ: 583686, ~: 583671) +IdRegistryTest:testInitialGracePeriod() (gas: 5610) +IdRegistryTest:testInitialMigrationTimestamp() (gas: 7710) +IdRegistryTest:testInitialMigrator() (gas: 9787) +IdRegistryTest:testInitialStateIsNotMigrated() (gas: 7703) +IdRegistryTest:testName() (gas: 7039) +IdRegistryTest:testTransferAndChangeRecoveryTypehash() (gas: 5509) +IdRegistryTest:testTransferTypehash() (gas: 5556) +IdRegistryTest:testVersion() (gas: 7057) +KeyGatewayTest:testFuzzAdd(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 316251, ~: 305408) +KeyGatewayTest:testFuzzAddFor(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 350154, ~: 338711) +KeyGatewayTest:testFuzzAddForRevertsBadSig(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 208905, ~: 208887) +KeyGatewayTest:testFuzzAddForRevertsExpiredSig(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 166751, ~: 166651) +KeyGatewayTest:testFuzzAddForRevertsInvalidSig(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 213188, ~: 213171) +KeyGatewayTest:testFuzzAddForRevertsNoFid(address,uint256,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 110513, ~: 110424) +KeyGatewayTest:testFuzzAddForRevertsPaused(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 171206, ~: 171109) +KeyGatewayTest:testFuzzAddForRevertsUsedNonce(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 214458, ~: 214441) +KeyGatewayTest:testFuzzAddRevertsIfRemoved(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 338600, ~: 321995) +KeyGatewayTest:testFuzzAddRevertsIfStateNotNull(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 314716, ~: 304192) +KeyGatewayTest:testFuzzAddRevertsInvalidMetadata(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 312769, ~: 302303) +KeyGatewayTest:testFuzzAddRevertsMaxKeys(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 1587785, ~: 1441562) +KeyGatewayTest:testFuzzAddRevertsPaused(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 187168, ~: 187232) +KeyGatewayTest:testFuzzAddRevertsUnlessFidOwner(address,address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 184451, ~: 184676) +KeyGatewayTest:testFuzzAddRevertsUnregisteredValidator(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 156753, ~: 156847) +KeyGatewayTest:testFuzzOnlyAuthorizedCanPause(address) (runs: 519, μ: 15579, ~: 15579) +KeyGatewayTest:testFuzzOnlyOwnerCanUnpause(address) (runs: 519, μ: 13518, ~: 13518) +KeyGatewayTest:testFuzzPauseUnpauseGuardian(address) (runs: 519, μ: 48417, ~: 48403) +KeyGatewayTest:testFuzzPauseUnpauseOwner() (gas: 28164) +KeyGatewayTest:testVersion() (gas: 7027) +KeyRegistryIntegrationTest:testFuzzAdd(address,uint256,address,bytes,uint40) (runs: 519, μ: 334701, ~: 335048) +KeyRegistryIntegrationTest:testFuzzAddRevertsInvalidSig(address,uint256,uint256,address,bytes,uint40) (runs: 519, μ: 332786, ~: 328632) +KeyRegistryIntegrationTest:testFuzzAddRevertsLongKey(address,uint256,address,bytes,uint40,uint8) (runs: 519, μ: 326669, ~: 324052) +KeyRegistryIntegrationTest:testFuzzAddRevertsShortKey(address,uint256,address,bytes,uint40,uint8) (runs: 519, μ: 293243, ~: 296351) +KeyRegistryTest:testBulkAddCannotReAdd() (gas: 259467) +KeyRegistryTest:testBulkAddEmitsEvent() (gas: 446599) +KeyRegistryTest:testBulkAddRevertsWhenUnpaused() (gas: 59152) +KeyRegistryTest:testBulkResetEmitsEvent() (gas: 376723) +KeyRegistryTest:testBulkResetRevertsIfRunTwice() (gas: 216502) +KeyRegistryTest:testBulkResetRevertsWithoutAdding() (gas: 60472) +KeyRegistryTest:testFreezeKeyGatewayRevertsWhenFrozen() (gas: 37850) +KeyRegistryTest:testFuzzAdd(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 308656, ~: 297784) +KeyRegistryTest:testFuzzAddRevertsIfRemoved(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 331227, ~: 313916) +KeyRegistryTest:testFuzzAddRevertsIfStateNotNull(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 305411, ~: 294864) +KeyRegistryTest:testFuzzAddRevertsInvalidMetadata(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 305384, ~: 294889) +KeyRegistryTest:testFuzzAddRevertsMaxKeys(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 1570767, ~: 1424542) +KeyRegistryTest:testFuzzAddRevertsPaused(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 183925, ~: 183954) +KeyRegistryTest:testFuzzAddRevertsUnlessRegistration(address,address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 172194, ~: 172224) +KeyRegistryTest:testFuzzAddRevertsUnregisteredValidator(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 146865, ~: 146921) +KeyRegistryTest:testFuzzBulkAddKeyForMigrationDuringGracePeriod(uint40) (runs: 519, μ: 166676, ~: 166401) +KeyRegistryTest:testFuzzBulkAddSignerForMigration(uint256[],uint8) (runs: 518, μ: 23114762, ~: 14119250) +KeyRegistryTest:testFuzzBulkAddSignerForMigrationAfterGracePeriodRevertsUnauthorized(uint40) (runs: 519, μ: 32064, ~: 32022) +KeyRegistryTest:testFuzzBulkRemoveSignerForMigration(uint256[],uint8) (runs: 518, μ: 21616829, ~: 13628366) +KeyRegistryTest:testFuzzBulkRemoveSignerForMigrationAfterGracePeriodRevertsUnauthorized(uint40) (runs: 519, μ: 31571, ~: 31529) +KeyRegistryTest:testFuzzBulkRemoveSignerForMigrationDuringGracePeriod(uint40) (runs: 519, μ: 136745, ~: 136529) +KeyRegistryTest:testFuzzBulkRemoveSignerForMigrationRevertsWhenUnpaused() (gas: 22338) +KeyRegistryTest:testFuzzCannotMigrateTwice(uint40) (runs: 519, μ: 28575, ~: 28562) +KeyRegistryTest:testFuzzKeyAt(address,address,uint32,uint8,uint16) (runs: 519, μ: 6087004, ~: 5406161) +KeyRegistryTest:testFuzzKeyCounts(address,address,uint32,uint8,uint16,uint16) (runs: 519, μ: 4580485, ~: 4105480) +KeyRegistryTest:testFuzzKeyHelpersRevertInvalidState() (gas: 22046) +KeyRegistryTest:testFuzzKeysOf(address,address,uint32,uint8,uint16) (runs: 519, μ: 6022105, ~: 5348811) +KeyRegistryTest:testFuzzKeysOfPaged(address,address,bool,uint32,uint8) (runs: 519, μ: 3340797, ~: 2804329) +KeyRegistryTest:testFuzzKeysOfPagedIndexEqualToLength(address,address,uint32,uint8) (runs: 519, μ: 2555299, ~: 2555484) +KeyRegistryTest:testFuzzKeysOfPagedIndexGreaterThanLength(address,address,uint32,uint8) (runs: 519, μ: 2555298, ~: 2555483) +KeyRegistryTest:testFuzzKeysOfPagedNeverReverts(address,address,uint32,uint8,uint256,uint256) (runs: 519, μ: 2556397, ~: 2555413) +KeyRegistryTest:testFuzzMigration(uint40) (runs: 518, μ: 23308, ~: 23308) +KeyRegistryTest:testFuzzOnlyAdminCanPause(address) (runs: 519, μ: 15603, ~: 15603) +KeyRegistryTest:testFuzzOnlyAdminCanSetIdRegistry(address,address) (runs: 519, μ: 13767, ~: 13767) +KeyRegistryTest:testFuzzOnlyAdminCanSetKeyGateway(address,address) (runs: 519, μ: 13746, ~: 13746) +KeyRegistryTest:testFuzzOnlyAdminCanSetMaxKeysPerFid(address,uint256) (runs: 519, μ: 13610, ~: 13610) +KeyRegistryTest:testFuzzOnlyAdminCanSetValidator(address,uint32,uint8,address) (runs: 519, μ: 19502, ~: 19459) +KeyRegistryTest:testFuzzOnlyMigratorCanMigrate(address) (runs: 519, μ: 17351, ~: 17351) +KeyRegistryTest:testFuzzOwnerCanSetMigrator(address) (runs: 519, μ: 25147, ~: 25166) +KeyRegistryTest:testFuzzRemove(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 368593, ~: 349269) +KeyRegistryTest:testFuzzRemoveFor(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 403341, ~: 384545) +KeyRegistryTest:testFuzzRemoveForRevertsBadSig(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 343462, ~: 332436) +KeyRegistryTest:testFuzzRemoveForRevertsExpiredSig(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 340049, ~: 329015) +KeyRegistryTest:testFuzzRemoveForRevertsInvalidSig(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 347504, ~: 336470) +KeyRegistryTest:testFuzzRemoveForRevertsNoFid(address,uint256,bytes,uint40) (runs: 519, μ: 57105, ~: 57069) +KeyRegistryTest:testFuzzRemoveForRevertsUsedNonce(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 348803, ~: 337769) +KeyRegistryTest:testFuzzRemoveForRevertsWhenPaused(address,uint256,address,uint32,bytes,uint8,bytes,uint40) (runs: 519, μ: 341308, ~: 330279) +KeyRegistryTest:testFuzzRemoveRevertsIfNull(address,address,bytes) (runs: 519, μ: 129405, ~: 129484) +KeyRegistryTest:testFuzzRemoveRevertsIfRemoved(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 329452, ~: 312015) +KeyRegistryTest:testFuzzRemoveRevertsUnlessFidOwner(address,address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 305706, ~: 295899) +KeyRegistryTest:testFuzzRemoveRevertsWhenPaused(address,address,uint32,bytes,uint8,bytes) (runs: 519, μ: 348957, ~: 333320) +KeyRegistryTest:testFuzzSetIdRegistry(address) (runs: 519, μ: 22935, ~: 22954) +KeyRegistryTest:testFuzzSetKeyGateway(address) (runs: 519, μ: 40108, ~: 40185) +KeyRegistryTest:testFuzzSetKeyGatewayRevertsWhenFrozen(address) (runs: 519, μ: 39984, ~: 39984) +KeyRegistryTest:testFuzzSetMaxKeysPerFid(uint256) (runs: 519, μ: 26661, ~: 26651) +KeyRegistryTest:testFuzzSetMaxKeysPerFidRevertsLessThanOrEqualToCurrentMax(uint256) (runs: 519, μ: 21606, ~: 21647) +KeyRegistryTest:testFuzzSetMigratorRevertsWhenMigrated(address) (runs: 519, μ: 24853, ~: 24853) +KeyRegistryTest:testFuzzSetMigratorRevertsWhenUnpaused(address) (runs: 519, μ: 20100, ~: 20100) +KeyRegistryTest:testFuzzSetValidator(uint32,uint8,address) (runs: 519, μ: 47993, ~: 48060) +KeyRegistryTest:testFuzzSetValidatorRevertsZeroKeyType(uint8,address) (runs: 519, μ: 17519, ~: 17484) +KeyRegistryTest:testFuzzSetValidatorRevertsZeroMetadataType(uint32,address) (runs: 519, μ: 17512, ~: 17502) +KeyRegistryTest:testInitialGracePeriod() (gas: 5624) +KeyRegistryTest:testInitialIdRegistry() (gas: 9832) +KeyRegistryTest:testInitialMigrationTimestamp() (gas: 7707) +KeyRegistryTest:testInitialMigrator() (gas: 9789) +KeyRegistryTest:testInitialOwner() (gas: 9847) +KeyRegistryTest:testInitialStateIsNotMigrated() (gas: 7715) +KeyRegistryTest:testOnlyOwnerCanFreezeKeyGateway(address) (runs: 519, μ: 13517, ~: 13517) +KeyRegistryTest:testPauseUnpause() (gas: 29100) +KeyRegistryTest:testRemoveTypeHash() (gas: 5575) +KeyRegistryTest:testVersion() (gas: 7149) +RecoveryProxyTest:testFuzzChangeOwner(address,uint256,uint40,address) (runs: 519, μ: 184683, ~: 184704) +RecoveryProxyTest:testFuzzOnlyOwnerCanSetIdRegistry(address,address) (runs: 519, μ: 13643, ~: 13643) +RecoveryProxyTest:testFuzzRecoveryByProxy(address,uint256,uint40) (runs: 519, μ: 170364, ~: 170345) +RecoveryProxyTest:testFuzzRecoveryByProxyRevertsUnauthorized(address,uint256,uint40,address) (runs: 519, μ: 137562, ~: 137776) +RecoveryProxyTest:testFuzzSetIdRegistry(address) (runs: 519, μ: 22612, ~: 22636) +RecoveryProxyTest:testIdRegistry() (gas: 9706) +RecoveryProxyTest:testInitialOwner() (gas: 9744) +SignedKeyRequestValidatorTest:testFuzzEncodeDecodeMetadata(uint256,address,bytes,uint256) (runs: 519, μ: 10486, ~: 10298) +SignedKeyRequestValidatorTest:testFuzzOnlyAdminCanSetIdRegistry(address,address) (runs: 519, μ: 13650, ~: 13650) +SignedKeyRequestValidatorTest:testFuzzSetIdRegistry(address) (runs: 519, μ: 22725, ~: 22735) +SignedKeyRequestValidatorTest:testFuzzValidate(uint256,uint256,bytes,uint40) (runs: 519, μ: 112526, ~: 112367) +SignedKeyRequestValidatorTest:testFuzzValidateBadSig(uint256,uint256,bytes,uint40) (runs: 519, μ: 113924, ~: 113765) +SignedKeyRequestValidatorTest:testFuzzValidateExpired(uint256,uint256,bytes,uint256,uint40) (runs: 519, μ: 106791, ~: 106646) +SignedKeyRequestValidatorTest:testFuzzValidateLongKey(uint256,uint256,bytes,uint40,uint8) (runs: 519, μ: 108611, ~: 108459) +SignedKeyRequestValidatorTest:testFuzzValidateShortKey(uint256,uint256,bytes,uint40,uint8) (runs: 519, μ: 107684, ~: 107381) +SignedKeyRequestValidatorTest:testFuzzValidateUnownedAppFid(uint256,uint256,bytes,uint40) (runs: 519, μ: 106064, ~: 105905) +SignedKeyRequestValidatorTest:testFuzzValidateWrongPubKey(uint256,uint256,bytes,bytes,uint40) (runs: 519, μ: 117548, ~: 117397) +SignedKeyRequestValidatorTest:testFuzzValidateWrongSigner(uint256,uint256,bytes,address,uint40) (runs: 519, μ: 108400, ~: 108258) +SignedKeyRequestValidatorTest:testMetadataTypeHash() (gas: 5488) +SignedKeyRequestValidatorTest:testVersion() (gas: 6994) StorageRegistryGasUsageTest:testGasBatchCredit() (gas: 173053) StorageRegistryGasUsageTest:testGasBatchRent() (gas: 270579) StorageRegistryGasUsageTest:testGasContinuousCredit() (gas: 166530) StorageRegistryGasUsageTest:testGasCredit() (gas: 81890) -StorageRegistryGasUsageTest:testGasRent() (gas: 163250) \ No newline at end of file +StorageRegistryGasUsageTest:testGasRent() (gas: 163250) +StorageRegistryTest:testBatchRentCheckedMath() (gas: 29517) +StorageRegistryTest:testContinuousCreditAmounts() (gas: 2030708) +StorageRegistryTest:testContinuousCreditEvents() (gas: 89890632) +StorageRegistryTest:testDefaultAdmin() (gas: 10826) +StorageRegistryTest:testDeprecationTimestampDefault() (gas: 7783) +StorageRegistryTest:testEthUSDPriceDefault() (gas: 7667) +StorageRegistryTest:testFuzzBatchCredit(uint256[],uint32) (runs: 517, μ: 623875, ~: 613911) +StorageRegistryTest:testFuzzBatchCreditRevertsExceedsCapacity(uint256[],uint32) (runs: 518, μ: 75628, ~: 75628) +StorageRegistryTest:testFuzzBatchCreditRevertsIfDeprecated(uint256[],uint32) (runs: 519, μ: 22159, ~: 22160) +StorageRegistryTest:testFuzzBatchCreditRevertsIfPaused(uint256[],uint32) (runs: 519, μ: 32749, ~: 32751) +StorageRegistryTest:testFuzzBatchCreditRevertsZeroAmount(uint256[]) (runs: 519, μ: 18959, ~: 18949) +StorageRegistryTest:testFuzzBatchRent(address,uint256[],uint16[]) (runs: 519, μ: 530271, ~: 477946) +StorageRegistryTest:testFuzzBatchRentCachedPrice(address,uint256[],uint16[],int256,uint256) (runs: 519, μ: 987266, ~: 883180) +StorageRegistryTest:testFuzzBatchRentFailedRefundRevertsCallFailed(uint256[],uint16[],uint256) (runs: 518, μ: 349230, ~: 327627) +StorageRegistryTest:testFuzzBatchRentPriceRefresh(address,uint256[],uint16[],int256) (runs: 519, μ: 1012864, ~: 887328) +StorageRegistryTest:testFuzzBatchRentRefundsExcessPayment(uint256[],uint16[],uint256) (runs: 518, μ: 346248, ~: 324645) +StorageRegistryTest:testFuzzBatchRentRevertsEmptyArray(address,uint256[],uint256[],uint256) (runs: 519, μ: 49454, ~: 47742) +StorageRegistryTest:testFuzzBatchRentRevertsExceedsCapacity(address,uint256[],uint16[]) (runs: 519, μ: 335312, ~: 307498) +StorageRegistryTest:testFuzzBatchRentRevertsIfDeprecated(address,uint256[],uint16[]) (runs: 519, μ: 138080, ~: 127600) +StorageRegistryTest:testFuzzBatchRentRevertsIfPaused(address,uint256[],uint16[]) (runs: 519, μ: 144695, ~: 134216) +StorageRegistryTest:testFuzzBatchRentRevertsInsufficientPayment(address,uint256[],uint16[],uint256) (runs: 519, μ: 336085, ~: 303874) +StorageRegistryTest:testFuzzBatchRentRevertsMismatchedArrayLength(address,uint256[],uint16[]) (runs: 519, μ: 139414, ~: 128934) +StorageRegistryTest:testFuzzCannotSetMaxEqualOrBelowMin(uint256) (runs: 519, μ: 20440, ~: 20766) +StorageRegistryTest:testFuzzCannotSetMinEqualOrAboveMax(uint256) (runs: 519, μ: 20402, ~: 20088) +StorageRegistryTest:testFuzzContinuousCredit(uint16,uint256,uint32) (runs: 515, μ: 850291, ~: 726139) +StorageRegistryTest:testFuzzContinuousCreditRevertsExceedsCapacity(uint16,uint256,uint32) (runs: 519, μ: 76041, ~: 76214) +StorageRegistryTest:testFuzzContinuousCreditRevertsIfDeprecated(uint16,uint256,uint32) (runs: 519, μ: 22745, ~: 22922) +StorageRegistryTest:testFuzzContinuousCreditRevertsIfPaused(uint16,uint256,uint32) (runs: 519, μ: 33337, ~: 33514) +StorageRegistryTest:testFuzzContinuousCreditRevertsStartGteEnd(uint16,uint256) (runs: 519, μ: 22195, ~: 22365) +StorageRegistryTest:testFuzzContinuousCreditRevertsZeroAmount(uint16,uint256) (runs: 519, μ: 22117, ~: 22309) +StorageRegistryTest:testFuzzCredit(uint256,uint32) (runs: 519, μ: 53034, ~: 52850) +StorageRegistryTest:testFuzzCreditRevertsExceedsCapacity(uint256,uint32) (runs: 519, μ: 72283, ~: 72273) +StorageRegistryTest:testFuzzCreditRevertsIfDeprecated(uint256,uint32) (runs: 519, μ: 16723, ~: 16723) +StorageRegistryTest:testFuzzCreditRevertsIfPaused(uint256,uint32) (runs: 519, μ: 27344, ~: 27344) +StorageRegistryTest:testFuzzCreditRevertsZeroUnits(uint256) (runs: 519, μ: 17531, ~: 17531) +StorageRegistryTest:testFuzzInitialPrice(uint128) (runs: 519, μ: 14756, ~: 14756) +StorageRegistryTest:testFuzzOnlyAuthorizedCanRefreshPrice(address) (runs: 519, μ: 17971, ~: 17971) +StorageRegistryTest:testFuzzOnlyOperatorCanBatchCredit(address,uint256[],uint256) (runs: 519, μ: 15164, ~: 15161) +StorageRegistryTest:testFuzzOnlyOperatorCanCredit(address,uint256,uint256) (runs: 519, μ: 13731, ~: 13731) +StorageRegistryTest:testFuzzOnlyOwnerCanPause(address) (runs: 519, μ: 13562, ~: 13562) +StorageRegistryTest:testFuzzOnlyOwnerCanSetCacheDuration(address,uint256) (runs: 519, μ: 13693, ~: 13693) +StorageRegistryTest:testFuzzOnlyOwnerCanSetDeprecationTime(address,uint256) (runs: 519, μ: 13602, ~: 13602) +StorageRegistryTest:testFuzzOnlyOwnerCanSetFixedEthUsdPrice(address,uint256) (runs: 519, μ: 13667, ~: 13667) +StorageRegistryTest:testFuzzOnlyOwnerCanSetGracePeriod(address,uint256) (runs: 519, μ: 13618, ~: 13618) +StorageRegistryTest:testFuzzOnlyOwnerCanSetMaxAge(address,uint256) (runs: 519, μ: 13667, ~: 13667) +StorageRegistryTest:testFuzzOnlyOwnerCanSetMaxAnswer(address,uint256) (runs: 519, μ: 13644, ~: 13644) +StorageRegistryTest:testFuzzOnlyOwnerCanSetMaxUnits(address,uint256) (runs: 519, μ: 13613, ~: 13613) +StorageRegistryTest:testFuzzOnlyOwnerCanSetMinAnswer(address,uint256) (runs: 519, μ: 13599, ~: 13599) +StorageRegistryTest:testFuzzOnlyOwnerCanSetPriceFeed(address,address) (runs: 519, μ: 13767, ~: 13767) +StorageRegistryTest:testFuzzOnlyOwnerCanSetUSDUnitPrice(address,uint256) (runs: 519, μ: 13646, ~: 13646) +StorageRegistryTest:testFuzzOnlyOwnerCanSetUptimeFeed(address,address) (runs: 519, μ: 13789, ~: 13789) +StorageRegistryTest:testFuzzOnlyOwnerCanSetVault(address,address) (runs: 519, μ: 13792, ~: 13792) +StorageRegistryTest:testFuzzOnlyOwnerCanUnpause(address) (runs: 519, μ: 13519, ~: 13519) +StorageRegistryTest:testFuzzOnlyTreasurerCanWithdraw(address,uint256) (runs: 519, μ: 11626, ~: 11626) +StorageRegistryTest:testFuzzPrice(uint48,uint128,int256) (runs: 519, μ: 92199, ~: 92340) +StorageRegistryTest:testFuzzPriceCached(uint48,uint128,int256) (runs: 519, μ: 46465, ~: 46346) +StorageRegistryTest:testFuzzPriceFeedFailure(address,uint256,uint256) (runs: 519, μ: 175498, ~: 175781) +StorageRegistryTest:testFuzzPriceFeedRevertsAnswerBelowBound(uint256) (runs: 519, μ: 90708, ~: 91030) +StorageRegistryTest:testFuzzPriceFeedRevertsInvalidPrice(int256) (runs: 519, μ: 54140, ~: 54214) +StorageRegistryTest:testFuzzRemoveFixedEthUsdPriceReenablesPriceFeed(uint256) (runs: 519, μ: 49624, ~: 49652) +StorageRegistryTest:testFuzzRent(address,uint256,uint200) (runs: 519, μ: 77171, ~: 77468) +StorageRegistryTest:testFuzzRentAndWithdraw(address,uint256,uint200,uint256) (runs: 519, μ: 127039, ~: 127173) +StorageRegistryTest:testFuzzRentCachedPrice(address,uint256,uint200,address,uint256,uint200,int256,uint256) (runs: 519, μ: 140745, ~: 140830) +StorageRegistryTest:testFuzzRentFailedRefundRevertsCallFailed(uint256,uint256,uint256) (runs: 519, μ: 81314, ~: 81553) +StorageRegistryTest:testFuzzRentFixedPrice(address,uint256,uint200,address,uint256,uint200,int256,uint256) (runs: 519, μ: 186513, ~: 186453) +StorageRegistryTest:testFuzzRentIntraBlockPriceDecrease(address,uint256,uint200,address,uint256,uint200,uint256) (runs: 519, μ: 171364, ~: 171561) +StorageRegistryTest:testFuzzRentIntraBlockPriceIncrease(address,uint256,uint200,address,uint256,uint200,uint256) (runs: 516, μ: 170891, ~: 171062) +StorageRegistryTest:testFuzzRentPriceRefresh(address,uint256,uint200,address,uint256,uint200,int256) (runs: 519, μ: 175359, ~: 175331) +StorageRegistryTest:testFuzzRentRefundsExcessPayment(uint256,uint256,uint256) (runs: 519, μ: 81569, ~: 81808) +StorageRegistryTest:testFuzzRentRevertsExceedsCapacity(address,uint256,uint256) (runs: 519, μ: 83814, ~: 84097) +StorageRegistryTest:testFuzzRentRevertsIfDeprecated(address,uint256,uint256) (runs: 519, μ: 34569, ~: 34855) +StorageRegistryTest:testFuzzRentRevertsInsufficientPayment(address,uint256,uint256,uint256) (runs: 519, μ: 53179, ~: 53159) +StorageRegistryTest:testFuzzRentRevertsWhenPaused(address,uint256,uint256) (runs: 519, μ: 55672, ~: 55955) +StorageRegistryTest:testFuzzRentRevertsZeroUnits(address,uint256) (runs: 519, μ: 27306, ~: 27306) +StorageRegistryTest:testFuzzSetCacheDuration(uint256) (runs: 519, μ: 22564, ~: 22629) +StorageRegistryTest:testFuzzSetDeprecationTime(uint256) (runs: 519, μ: 26576, ~: 26499) +StorageRegistryTest:testFuzzSetDeprecationTimeRevertsInPast(uint256) (runs: 519, μ: 19634, ~: 19637) +StorageRegistryTest:testFuzzSetFixedEthUsdPrice(uint256) (runs: 519, μ: 50371, ~: 50394) +StorageRegistryTest:testFuzzSetFixedEthUsdPriceOverridesPriceFeed(uint256) (runs: 519, μ: 61710, ~: 61733) +StorageRegistryTest:testFuzzSetFixedEthUsdPriceRevertsGreaterThanMaxPrice(uint256) (runs: 519, μ: 25585, ~: 25271) +StorageRegistryTest:testFuzzSetFixedEthUsdPriceRevertsLessThanMinPrice(uint256) (runs: 519, μ: 23517, ~: 23839) +StorageRegistryTest:testFuzzSetGracePeriod(uint256) (runs: 519, μ: 22628, ~: 22693) +StorageRegistryTest:testFuzzSetMaxAge(uint256) (runs: 519, μ: 22612, ~: 22677) +StorageRegistryTest:testFuzzSetMaxAnswer(uint256) (runs: 519, μ: 29978, ~: 29671) +StorageRegistryTest:testFuzzSetMaxUnitsEmitsEvent(uint256) (runs: 519, μ: 22566, ~: 22631) +StorageRegistryTest:testFuzzSetMinAnswer(uint256) (runs: 519, μ: 29841, ~: 30114) +StorageRegistryTest:testFuzzSetPriceFeed(address) (runs: 519, μ: 23103, ~: 23113) +StorageRegistryTest:testFuzzSetUSDUnitPrice(uint256) (runs: 519, μ: 22610, ~: 22675) +StorageRegistryTest:testFuzzSetUptimeFeed(address) (runs: 519, μ: 23148, ~: 23158) +StorageRegistryTest:testFuzzSetVault(address) (runs: 519, μ: 24689, ~: 24689) +StorageRegistryTest:testFuzzUnitPriceCached(uint48,int256) (runs: 519, μ: 46098, ~: 45834) +StorageRegistryTest:testFuzzUnitPriceRefresh(uint48,int256) (runs: 519, μ: 91982, ~: 92111) +StorageRegistryTest:testFuzzUptimeFeedFailure(address,uint256,uint256) (runs: 519, μ: 142022, ~: 142305) +StorageRegistryTest:testFuzzUptimeFeedRevertsInvalidTimestamp(uint256) (runs: 519, μ: 63837, ~: 63817) +StorageRegistryTest:testFuzzUptimeFeedRevertsSequencerDown(int256) (runs: 519, μ: 58615, ~: 58615) +StorageRegistryTest:testFuzzWithdraw(uint256) (runs: 519, μ: 59431, ~: 59432) +StorageRegistryTest:testFuzzWithdrawalRevertsCallFailed(uint256) (runs: 519, μ: 36355, ~: 36446) +StorageRegistryTest:testFuzzWithdrawalRevertsInsufficientFunds(uint256) (runs: 519, μ: 53246, ~: 53243) +StorageRegistryTest:testInitialPriceUpdate() (gas: 46422) +StorageRegistryTest:testInitialUnitPrice() (gas: 14445) +StorageRegistryTest:testLastPriceFeedUpdateBlockDefault() (gas: 7643) +StorageRegistryTest:testLastPriceFeedUpdateDefault() (gas: 7688) +StorageRegistryTest:testMaxUnitsDefault() (gas: 7668) +StorageRegistryTest:testOnlyOperatorCanContinuousCredit(address,uint16,uint256,uint32) (runs: 519, μ: 19867, ~: 20004) +StorageRegistryTest:testPauseUnpause() (gas: 22025) +StorageRegistryTest:testPrevEthUSDPriceDefault() (gas: 7731) +StorageRegistryTest:testPriceFeedCacheDurationDefault() (gas: 7646) +StorageRegistryTest:testPriceFeedDefault() (gas: 9967) +StorageRegistryTest:testPriceFeedMaxAgeDefault() (gas: 7712) +StorageRegistryTest:testPriceFeedMaxAnswerDefault() (gas: 7751) +StorageRegistryTest:testPriceFeedMinAnswerDefault() (gas: 7668) +StorageRegistryTest:testPriceFeedRevertsAnswerAboveBound(uint256) (runs: 519, μ: 92609, ~: 92579) +StorageRegistryTest:testPriceFeedRevertsIncompleteRound() (gas: 93495) +StorageRegistryTest:testPriceFeedRevertsInvalidTimestamp() (gas: 98418) +StorageRegistryTest:testPriceFeedRevertsStaleAnswerByMaxAge() (gas: 98156) +StorageRegistryTest:testPriceFeedRevertsZeroRoundId() (gas: 75246) +StorageRegistryTest:testPriceRoundsUp() (gas: 89084) +StorageRegistryTest:testRentedUnitsDefault() (gas: 7623) +StorageRegistryTest:testRoles() (gas: 7124) +StorageRegistryTest:testSetVaultCannotBeZeroAddress() (gas: 13187) +StorageRegistryTest:testUptimeFeedDefault() (gas: 9934) +StorageRegistryTest:testUptimeFeedGracePeriodDefault() (gas: 7733) +StorageRegistryTest:testUptimeFeedRevertsGracePeriodNotOver() (gas: 60778) +StorageRegistryTest:testUptimeFeedRevertsIncompleteRound() (gas: 74686) +StorageRegistryTest:testUptimeFeedRevertsZeroRoundId() (gas: 56498) +StorageRegistryTest:testUsdUnitPriceDefault() (gas: 7668) +StorageRegistryTest:testVersion() (gas: 7090) +TierRegistryTest:testFuzzAddMultipleTiers(uint256,uint256,uint64,address) (runs: 518, μ: 311404, ~: 311400) +TierRegistryTest:testFuzzBatchCreditTier(uint32,address,uint256[],uint16) (runs: 518, μ: 841700, ~: 849292) +TierRegistryTest:testFuzzBatchCreditTierInvalidTier(uint256,uint32,address,uint256[],uint16) (runs: 519, μ: 61779, ~: 61773) +TierRegistryTest:testFuzzBatchCreditTierTooLittleTimeCancelsBatch(uint32,address,uint256[]) (runs: 518, μ: 198384, ~: 198372) +TierRegistryTest:testFuzzBatchCreditTierTooMuchTimeCancelsBatch(uint32,address,uint256[]) (runs: 518, μ: 198450, ~: 198438) +TierRegistryTest:testFuzzBatchCreditTierUnauthorizedCaller(address,uint32,address,uint256[],uint16) (runs: 518, μ: 201459, ~: 201440) +TierRegistryTest:testFuzzBatchCreditTierWhenMigrated(uint32,address,uint256[],uint16,uint32) (runs: 518, μ: 208683, ~: 208691) +TierRegistryTest:testFuzzBatchCreditTierWhenUnpaused(uint32,address,uint256[],uint16) (runs: 518, μ: 178775, ~: 178770) +TierRegistryTest:testFuzzBatchCreditTierZeroFids(uint32,address,uint16) (runs: 518, μ: 200022, ~: 199994) +TierRegistryTest:testFuzzBatchCreditTierZeroTimeCancelsBatch(uint32,address,uint256[]) (runs: 518, μ: 198307, ~: 198295) +TierRegistryTest:testFuzzBatchPurchaseTier(address,uint32,address,uint256[],uint16[]) (runs: 517, μ: 786698, ~: 713521) +TierRegistryTest:testFuzzBatchPurchaseTierInvalidTier(uint256,address,uint32,address,uint256[],uint16[]) (runs: 519, μ: 97493, ~: 89169) +TierRegistryTest:testFuzzBatchPurchaseTierMismatchedInputs(address,uint32,address,uint256[],uint16[]) (runs: 518, μ: 230329, ~: 228575) +TierRegistryTest:testFuzzBatchPurchaseTierRevertsWithInsufficientApprovedFunds(address,uint32,address,uint256[],uint16[]) (runs: 517, μ: 569623, ~: 526730) +TierRegistryTest:testFuzzBatchPurchaseTierRevertsWithInsufficientFunds(address,uint32,address,uint256[],uint16[]) (runs: 517, μ: 572174, ~: 529281) +TierRegistryTest:testFuzzBatchPurchaseTierTooLittleTimeCancelsBatch(address,uint32,uint64,address,uint256[],uint16[]) (runs: 516, μ: 248681, ~: 238332) +TierRegistryTest:testFuzzBatchPurchaseTierTooMuchTimeTimeCancelsBatch(address,uint32,uint8,address,uint256[],uint16[]) (runs: 515, μ: 248592, ~: 238778) +TierRegistryTest:testFuzzBatchPurchaseTierWhilePaused(address,uint32,address,uint256[],uint16[]) (runs: 518, μ: 271626, ~: 260231) +TierRegistryTest:testFuzzBatchPurchaseTierZeroFids(address,uint32,address,uint16[]) (runs: 518, μ: 230599, ~: 234385) +TierRegistryTest:testFuzzBatchPurchaseTierZeroTimeCancelsBatch(address,uint32,address,uint256[],uint16[]) (runs: 518, μ: 250039, ~: 238644) +TierRegistryTest:testFuzzCannotMigrateTwice(uint40) (runs: 519, μ: 55210, ~: 55198) +TierRegistryTest:testFuzzDeactivateInactiveTier(uint256) (runs: 519, μ: 15293, ~: 15293) +TierRegistryTest:testFuzzGetPrice(uint64,address,uint64,address) (runs: 519, μ: 167288, ~: 167288) +TierRegistryTest:testFuzzGetPriceForInvalidTier(uint256,uint64,address,uint64,address) (runs: 519, μ: 22829, ~: 22829) +TierRegistryTest:testFuzzGetTierInfo(uint64,address,address) (runs: 519, μ: 168202, ~: 168202) +TierRegistryTest:testFuzzGetTierInfoForInvalidTier(uint256,address) (runs: 519, μ: 22675, ~: 22675) +TierRegistryTest:testFuzzMigration(uint40) (runs: 518, μ: 49949, ~: 49949) +TierRegistryTest:testFuzzOnlyGuardianCanPause(address) (runs: 519, μ: 15566, ~: 15566) +TierRegistryTest:testFuzzOnlyMigratorCanMigrate(address) (runs: 519, μ: 45994, ~: 45994) +TierRegistryTest:testFuzzOnlyOwnerCanAddTier(uint256,uint256,uint64,address,address) (runs: 519, μ: 19105, ~: 19105) +TierRegistryTest:testFuzzOnlyOwnerCanRescueTokens(address,address) (runs: 519, μ: 16310, ~: 16310) +TierRegistryTest:testFuzzOnlyOwnerCanUnpause(address) (runs: 519, μ: 13504, ~: 13504) +TierRegistryTest:testFuzzOwnerCanSetMigrator(address) (runs: 519, μ: 47910, ~: 47938) +TierRegistryTest:testFuzzPurchaseRemovedTier(uint256,uint64,uint64,address,address) (runs: 519, μ: 154935, ~: 154935) +TierRegistryTest:testFuzzPurchaseTier(uint256,uint64,uint64,address,address) (runs: 513, μ: 229787, ~: 229791) +TierRegistryTest:testFuzzPurchaseTierForTooLittleTime(uint256,uint64,address,address) (runs: 519, μ: 169898, ~: 169898) +TierRegistryTest:testFuzzPurchaseTierForTooMuchTime(uint256,uint64,address,address) (runs: 519, μ: 169932, ~: 169932) +TierRegistryTest:testFuzzPurchaseTierWhenPaused(uint256,uint64,uint64,address,address) (runs: 519, μ: 192139, ~: 192139) +TierRegistryTest:testFuzzPurchaseTierWithInsufficientApprovedFunds(uint256,uint64,uint64,address,address) (runs: 513, μ: 242479, ~: 242557) +TierRegistryTest:testFuzzPurchaseTierWithInsufficientFunds(uint256,uint64,uint64,address,address) (runs: 513, μ: 244692, ~: 244781) +TierRegistryTest:testFuzzPurchaseTierWithNoTime(uint256,uint64,address,address) (runs: 519, μ: 169523, ~: 169523) +TierRegistryTest:testFuzzPurchaseUnregisteredTier(uint256,uint256,uint64,uint64,address) (runs: 518, μ: 25392, ~: 25392) +TierRegistryTest:testFuzzRescueTokens(uint256,address) (runs: 519, μ: 71592, ~: 71931) +TierRegistryTest:testFuzzSetMigratorRevertsWhenMigrated(address) (runs: 519, μ: 47602, ~: 47602) +TierRegistryTest:testFuzzSetMigratorRevertsWhenUnpaused(address) (runs: 519, μ: 19906, ~: 19906) +TierRegistryTest:testFuzzSetTierInvalidMaxDays(address,uint256,uint64,address) (runs: 519, μ: 17971, ~: 17971) +TierRegistryTest:testFuzzSetTierInvalidMinDays(address,uint256,uint64,address) (runs: 519, μ: 17936, ~: 17936) +TierRegistryTest:testFuzzSetTierInvalidPrice(address,uint256,uint256,address) (runs: 519, μ: 18021, ~: 18017) +TierRegistryTest:testFuzzSetTierInvalidTierId(uint256,address,uint256,uint256,uint64,address) (runs: 519, μ: 18918, ~: 18915) +TierRegistryTest:testFuzzSetTierInvalidToken(uint256,uint256,uint64,address) (runs: 518, μ: 17868, ~: 17868) +TierRegistryTest:testFuzzSetTierInvalidVault(address,uint256,uint256,uint64) (runs: 519, μ: 18005, ~: 18001) +TierRegistryTest:testFuzzSetTierReverseMinAndMaxDays(address,uint256,uint256,uint64,address) (runs: 519, μ: 18778, ~: 18774) +TierRegistryTest:testFuzzViewStateForInactiveTier(uint256,uint256,uint64,address) (runs: 518, μ: 153450, ~: 153446) +TierRegistryTest:testInitialGracePeriod() (gas: 5624) +TierRegistryTest:testInitialMigrationTimestamp() (gas: 7709) +TierRegistryTest:testInitialMigrator() (gas: 9853) +TierRegistryTest:testInitialStateIsNotMigrated() (gas: 7739) +TierRegistryTest:testOwner() (gas: 9781) +TierRegistryTest:testVersion() (gas: 7010) \ No newline at end of file diff --git a/src/TierRegistry.sol b/src/TierRegistry.sol index 2900c29c..0109b7ac 100644 --- a/src/TierRegistry.sol +++ b/src/TierRegistry.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; -import {Ownable2Step} from "openzeppelin/contracts/access/Ownable2Step.sol"; -import {Pausable} from "openzeppelin/contracts/security/Pausable.sol"; +import {Migration} from "./abstract/Migration.sol"; import "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {ITierRegistry} from "./interfaces/ITierRegistry.sol"; @@ -14,7 +13,7 @@ import {ITierRegistry} from "./interfaces/ITierRegistry.sol"; * * @custom:security-contact security@merklemanufactory.com */ -contract TierRegistry is ITierRegistry, Ownable2Step, Pausable { +contract TierRegistry is ITierRegistry, Migration { using SafeERC20 for IERC20; /*////////////////////////////////////////////////////////////// @@ -27,7 +26,7 @@ contract TierRegistry is ITierRegistry, Ownable2Step, Pausable { string public constant VERSION = "2025.06.01"; /*////////////////////////////////////////////////////////////// - STORAGE + STORAGE //////////////////////////////////////////////////////////////*/ /** @@ -41,7 +40,7 @@ contract TierRegistry is ITierRegistry, Ownable2Step, Pausable { /** * @inheritdoc ITierRegistry */ - uint256 public nextTierId; + uint256 public nextTierId = 1; /*////////////////////////////////////////////////////////////// CONSTRUCTOR @@ -50,14 +49,10 @@ contract TierRegistry is ITierRegistry, Ownable2Step, Pausable { /** * @notice Set the initial parameters and pause the contract. * + * @param _migrator Migrator address. * @param _initialOwner Initial owner address. */ - constructor( - address _initialOwner - ) { - _transferOwnership(_initialOwner); - _pause(); - } + constructor(address _migrator, address _initialOwner) Migration(24 hours, _migrator, _initialOwner) {} /*////////////////////////////////////////////////////////////// VIEWS @@ -123,14 +118,9 @@ contract TierRegistry is ITierRegistry, Ownable2Step, Pausable { if (numDays < info.minDays) revert InvalidDuration(); if (numDays > info.maxDays) revert InvalidDuration(); totalCost += info.tokenPricePerDay * numDays; - } - - for (uint256 i; i < fids.length; ++i) { - // The payer field in the event will point to a contract if the caller is a contract emit PurchasedTier(fids[i], tier, forDays[i], msg.sender); } - // Payment is made in a single transaction to save gas info.paymentToken.safeTransferFrom(msg.sender, info.vault, totalCost); } @@ -138,6 +128,26 @@ contract TierRegistry is ITierRegistry, Ownable2Step, Pausable { PERMISSIONED ACTIONS //////////////////////////////////////////////////////////////*/ + /** + * @inheritdoc ITierRegistry + */ + function batchCreditTier(uint256 tier, uint256[] calldata fids, uint256 forDays) external onlyMigrator { + if (fids.length == 0) revert InvalidBatchInput(); + + TierInfo memory info = _tierInfoByTier[tier]; + if (!info.isActive) revert InvalidTier(); + + for (uint256 i; i < fids.length; ++i) { + if (forDays == 0) revert InvalidDuration(); + if (forDays < info.minDays) revert InvalidDuration(); + if (forDays > info.maxDays) revert InvalidDuration(); + emit PurchasedTier(fids[i], tier, forDays, msg.sender); + } + } + + /** + * @inheritdoc ITierRegistry + */ function setTier( uint256 tier, address paymentToken, @@ -152,6 +162,7 @@ contract TierRegistry is ITierRegistry, Ownable2Step, Pausable { if (minDays > maxDays) revert InvalidDuration(); if (tokenPricePerDay == 0) revert InvalidPrice(); if (vault == address(0)) revert InvalidVaultAddress(); + if (tier == 0) revert InvalidTier(); if (tier > nextTierId) revert InvalidTier(); emit SetTier(tier, minDays, maxDays, vault, paymentToken, tokenPricePerDay); @@ -186,14 +197,9 @@ contract TierRegistry is ITierRegistry, Ownable2Step, Pausable { /** * @inheritdoc ITierRegistry */ - function pause() external onlyOwner { - _pause(); - } - - /** - * @inheritdoc ITierRegistry - */ - function unpause() external onlyOwner { - _unpause(); + function sweepToken(address token, address to) external onlyOwner { + uint256 balance = IERC20(token).balanceOf(address(this)); + emit SweepToken(token, to, balance); + IERC20(token).safeTransfer(to, balance); } } diff --git a/src/interfaces/ITierRegistry.sol b/src/interfaces/ITierRegistry.sol index 2a5f6440..c4e02342 100644 --- a/src/interfaces/ITierRegistry.sol +++ b/src/interfaces/ITierRegistry.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.21; +import {IMigration} from "./abstract/IMigration.sol"; import "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /** * @title ITierRegistry * @notice Interface for the TierRegistry contract that manages tier purchases for Farcaster IDs */ -interface ITierRegistry { +interface ITierRegistry is IMigration { /** * @notice Information about a user tier * @param minDays Minimum number of days that can be purchased for this tier @@ -85,6 +86,14 @@ interface ITierRegistry { uint256 tokenPricePerDay ); + /** + * @notice Emitted when owner sweeps an ERC20 token balance + * @param token ERC20 token address + * @param to Address that receives the full balance + * @param balance Token balance sent + */ + event SweepToken(address indexed token, address to, uint256 balance); + /*////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////*/ @@ -105,7 +114,7 @@ interface ITierRegistry { function nextTierId() external view returns (uint256); /*////////////////////////////////////////////////////////////// - GETTERS + GETTERS //////////////////////////////////////////////////////////////*/ /** @@ -149,6 +158,14 @@ interface ITierRegistry { PERMISSIONED ACTIONS //////////////////////////////////////////////////////////////*/ + /** + * @notice Credit a tier to multiple Farcaster IDs in a single transaction + * @param tier The tier ID to credit for all FIDs + * @param fids Array of Farcaster IDs to credit for + * @param forDays Number of days to credit + */ + function batchCreditTier(uint256 tier, uint256[] calldata fids, uint256 forDays) external; + /** * @notice Update/create a user tier configuration * Only callable by owner. @@ -178,14 +195,9 @@ interface ITierRegistry { ) external; /** - * @notice Pause, disabling rentals and credits. - * Only callable by owner. - */ - function pause() external; - - /** - * @notice Unpause, enabling rentals and credits. - * Only callable by owner. + * @notice Rescue an ERC20 token accidentally sent to this contract + * @param token The token address + * @param to Receiver address that will receive the full token balance */ - function unpause() external; + function sweepToken(address token, address to) external; } diff --git a/src/interfaces/abstract/IMigration.sol b/src/interfaces/abstract/IMigration.sol index 4939b3a4..5eff8716 100644 --- a/src/interfaces/abstract/IMigration.sol +++ b/src/interfaces/abstract/IMigration.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; -interface IMigration { +import {IGuardians} from "./IGuardians.sol"; + +interface IMigration is IGuardians { /*////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ diff --git a/test/TierRegistry/TierRegistry.t.sol b/test/TierRegistry/TierRegistry.t.sol index 1d82db50..a6b81165 100644 --- a/test/TierRegistry/TierRegistry.t.sol +++ b/test/TierRegistry/TierRegistry.t.sol @@ -1,8 +1,10 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.21; +pragma solidity ^0.8.21; import "forge-std/Test.sol"; import {ITierRegistry} from "../../src/TierRegistry.sol"; +import {IGuardians} from "../../src/abstract/Guardians.sol"; +import {IMigration} from "../../src/interfaces/abstract/IMigration.sol"; import {TransferHelper} from "../../src/libraries/TransferHelper.sol"; import {TierRegistryTestSuite} from "./TierRegistryTestSuite.sol"; import "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -10,6 +12,10 @@ import "openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract TierRegistryTest is TierRegistryTestSuite { using SafeERC20 for IERC20; + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + event PurchasedTier(uint256 indexed fid, uint256 indexed tier, uint256 forDays, address payer); event DeactivateTier(uint256 indexed tier); event SetTier( @@ -20,13 +26,40 @@ contract TierRegistryTest is TierRegistryTestSuite { address paymentToken, uint256 tokenPricePerDay ); + event Migrated(uint256 indexed migratedAt); + event SetMigrator(address oldMigrator, address newMigrator); + event SweepToken(address indexed token, address to, uint256 balance); + + /*////////////////////////////////////////////////////////////// + PARAMETERS + //////////////////////////////////////////////////////////////*/ function testVersion() public { assertEq(tierRegistry.VERSION(), "2025.06.01"); } + function testOwner() public { + assertEq(tierRegistry.owner(), owner); + } + + function testInitialGracePeriod() public { + assertEq(tierRegistry.gracePeriod(), 1 days); + } + + function testInitialMigrationTimestamp() public { + assertEq(tierRegistry.migratedAt(), 0); + } + + function testInitialMigrator() public { + assertEq(tierRegistry.migrator(), migrator); + } + + function testInitialStateIsNotMigrated() public { + assertEq(tierRegistry.isMigrated(), false); + } + /*////////////////////////////////////////////////////////////// - PURCHASE TIER + PURCHASE TIER //////////////////////////////////////////////////////////////*/ function testFuzzPurchaseTier(uint256 fid, uint64 price, uint64 forDays, address payer, address vault) public { @@ -435,7 +468,7 @@ contract TierRegistryTest is TierRegistryTestSuite { } /*////////////////////////////////////////////////////////////// - EDIT TIERS + EDIT TIERS //////////////////////////////////////////////////////////////*/ function testFuzzAddMultipleTiers(uint256 daysBound1, uint256 daysBound2, uint64 price, address vault) public { @@ -446,9 +479,9 @@ contract TierRegistryTest is TierRegistryTestSuite { (uint256 minDays, uint256 maxDays) = daysBound1 < daysBound2 ? (daysBound1, daysBound2) : (daysBound2, daysBound1); uint256 tier1 = _addTier(address(token), price, minDays, maxDays, vault); - assertEq(tier1, 0); + assertEq(tier1, 1); uint256 tier2 = _addTier(address(token), price, minDays, maxDays, vault); - assertEq(tier2, 1); + assertEq(tier2, 2); } function testFuzzSetTierInvalidToken(uint256 minDays, uint256 maxDays, uint64 price, address vault) public { @@ -616,13 +649,13 @@ contract TierRegistryTest is TierRegistryTestSuite { PAUSABILITY //////////////////////////////////////////////////////////////*/ - function testFuzzOnlyOwnerCanPause( + function testFuzzOnlyGuardianCanPause( address caller ) public { vm.assume(caller != owner); vm.prank(caller); - vm.expectRevert("Ownable: caller is not the owner"); + vm.expectRevert(IGuardians.OnlyGuardian.selector); tierRegistry.pause(); } @@ -637,7 +670,7 @@ contract TierRegistryTest is TierRegistryTestSuite { } /*////////////////////////////////////////////////////////////// - GETTERS + GETTERS //////////////////////////////////////////////////////////////*/ function testFuzzGetPrice(uint64 price, address vault, uint64 forDays, address caller) public { @@ -688,6 +721,323 @@ contract TierRegistryTest is TierRegistryTestSuite { assertEq(tierInfo.isActive, false); } + /*////////////////////////////////////////////////////////////// + SET MIGRATOR + //////////////////////////////////////////////////////////////*/ + + function testFuzzOwnerCanSetMigrator( + address migrator + ) public { + address oldMigrator = tierRegistry.migrator(); + vm.prank(owner); + tierRegistry.pause(); + + vm.expectEmit(); + emit SetMigrator(oldMigrator, migrator); + vm.prank(owner); + tierRegistry.setMigrator(migrator); + + assertEq(tierRegistry.migrator(), migrator); + } + + function testFuzzSetMigratorRevertsWhenMigrated( + address migrator + ) public { + address oldMigrator = tierRegistry.migrator(); + vm.prank(owner); + tierRegistry.pause(); + + vm.prank(oldMigrator); + tierRegistry.migrate(); + + vm.prank(owner); + vm.expectRevert(IMigration.AlreadyMigrated.selector); + tierRegistry.setMigrator(migrator); + + assertEq(tierRegistry.migrator(), oldMigrator); + } + + function testFuzzSetMigratorRevertsWhenUnpaused( + address migrator + ) public { + address oldMigrator = tierRegistry.migrator(); + + vm.expectRevert("Pausable: not paused"); + vm.prank(owner); + tierRegistry.setMigrator(migrator); + vm.stopPrank(); + + assertEq(tierRegistry.migrator(), oldMigrator); + } + + /*////////////////////////////////////////////////////////////// + BATCH CREDIT + //////////////////////////////////////////////////////////////*/ + + function testFuzzBatchCreditTier(uint32 price, address vault, uint256[] calldata fids, uint16 _forDays) public { + vm.assume(fids.length > 0); + vm.assume(price != 0); + vm.assume(vault != address(0)); + + uint256 forDays = bound(_forDays, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS); + + uint256 tier = _addTier(address(token), price, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS, vault); + + vm.prank(owner); + tierRegistry.pause(); + + _batchCreditTier(tier, fids, forDays, migrator); + } + + function testFuzzBatchCreditTierWhenUnpaused( + uint32 price, + address vault, + uint256[] calldata fids, + uint16 _forDays + ) public { + vm.assume(fids.length > 0); + vm.assume(price != 0); + vm.assume(vault != address(0)); + + uint256 forDays = bound(_forDays, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS); + + uint256 tier = _addTier(address(token), price, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS, vault); + + vm.expectRevert("Pausable: not paused"); + vm.prank(migrator); + tierRegistry.batchCreditTier(tier, fids, forDays); + } + + function testFuzzBatchCreditTierZeroTimeCancelsBatch(uint32 price, address vault, uint256[] calldata fids) public { + vm.assume(fids.length > 0); + vm.assume(price != 0); + vm.assume(vault != address(0)); + + uint256 tier = _addTier(address(token), price, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS, vault); + + vm.prank(owner); + tierRegistry.pause(); + + vm.expectRevert(ITierRegistry.InvalidDuration.selector); + vm.prank(migrator); + tierRegistry.batchCreditTier(tier, fids, 0); + } + + function testFuzzBatchCreditTierTooLittleTimeCancelsBatch( + uint32 price, + address vault, + uint256[] calldata fids + ) public { + vm.assume(fids.length > 0); + vm.assume(price != 0); + vm.assume(vault != address(0)); + + uint256 tier = _addTier(address(token), price, 2, DEFAULT_MAX_DAYS, vault); + + vm.prank(owner); + tierRegistry.pause(); + + vm.expectRevert(ITierRegistry.InvalidDuration.selector); + vm.prank(migrator); + tierRegistry.batchCreditTier(tier, fids, 1); + } + + function testFuzzBatchCreditTierTooMuchTimeCancelsBatch( + uint32 price, + address vault, + uint256[] calldata fids + ) public { + vm.assume(fids.length > 0); + vm.assume(price != 0); + vm.assume(vault != address(0)); + + uint256 tier = _addTier(address(token), price, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS, vault); + + vm.prank(owner); + tierRegistry.pause(); + + vm.expectRevert(ITierRegistry.InvalidDuration.selector); + vm.prank(migrator); + tierRegistry.batchCreditTier(tier, fids, DEFAULT_MAX_DAYS + 1); + } + + function testFuzzBatchCreditTierZeroFids(uint32 price, address vault, uint16 _forDays) public { + vm.assume(price != 0); + vm.assume(vault != address(0)); + + uint256 forDays = bound(_forDays, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS); + uint256 tier = _addTier(address(token), price, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS, vault); + uint256[] memory fids = new uint256[](0); + + vm.prank(owner); + tierRegistry.pause(); + + vm.expectRevert(ITierRegistry.InvalidBatchInput.selector); + vm.prank(migrator); + tierRegistry.batchCreditTier(tier, fids, forDays); + } + + function testFuzzBatchCreditTierInvalidTier( + uint256 tier, + uint32 price, + address vault, + uint256[] calldata fids, + uint16 _forDays + ) public { + vm.assume(fids.length > 0); + vm.assume(price != 0); + vm.assume(vault != address(0)); + + uint256 forDays = bound(_forDays, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS); + + vm.prank(owner); + tierRegistry.pause(); + + vm.expectRevert(ITierRegistry.InvalidTier.selector); + vm.prank(migrator); + tierRegistry.batchCreditTier(tier, fids, forDays); + } + + function testFuzzBatchCreditTierWhenMigrated( + uint32 price, + address vault, + uint256[] calldata fids, + uint16 _forDays, + uint32 warpForward + ) public { + vm.assume(fids.length > 0); + vm.assume(price != 0); + vm.assume(vault != address(0)); + + vm.prank(owner); + tierRegistry.pause(); + + uint256 forDays = bound(_forDays, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS); + uint256 tier = _addTier(address(token), price, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS, vault); + + vm.prank(migrator); + tierRegistry.migrate(); + + vm.warp(block.timestamp + tierRegistry.gracePeriod() + 1 + warpForward); + + vm.expectRevert(IMigration.PermissionRevoked.selector); + vm.prank(migrator); + tierRegistry.batchCreditTier(tier, fids, forDays); + } + + function testFuzzBatchCreditTierUnauthorizedCaller( + address caller, + uint32 price, + address vault, + uint256[] calldata fids, + uint16 _forDays + ) public { + vm.assume(caller != migrator); + vm.assume(fids.length > 0); + vm.assume(price != 0); + vm.assume(vault != address(0)); + + uint256 forDays = bound(_forDays, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS); + uint256 tier = _addTier(address(token), price, DEFAULT_MIN_DAYS, DEFAULT_MAX_DAYS, vault); + + vm.prank(owner); + tierRegistry.pause(); + + vm.expectRevert(IMigration.OnlyMigrator.selector); + vm.prank(caller); + tierRegistry.batchCreditTier(tier, fids, forDays); + } + + /*////////////////////////////////////////////////////////////// + MIGRATION + //////////////////////////////////////////////////////////////*/ + + function testFuzzMigration( + uint40 timestamp + ) public { + vm.assume(timestamp != 0); + + vm.prank(owner); + tierRegistry.pause(); + + vm.warp(timestamp); + vm.expectEmit(); + emit Migrated(timestamp); + vm.prank(migrator); + tierRegistry.migrate(); + + assertEq(tierRegistry.isMigrated(), true); + assertEq(tierRegistry.migratedAt(), timestamp); + } + + function testFuzzOnlyMigratorCanMigrate( + address caller + ) public { + vm.assume(caller != migrator); + + vm.prank(owner); + tierRegistry.pause(); + + vm.prank(caller); + vm.expectRevert(IMigration.OnlyMigrator.selector); + tierRegistry.migrate(); + + assertEq(tierRegistry.isMigrated(), false); + assertEq(tierRegistry.migratedAt(), 0); + } + + function testFuzzCannotMigrateTwice( + uint40 timestamp + ) public { + vm.prank(owner); + tierRegistry.pause(); + + timestamp = uint40(bound(timestamp, 1, type(uint40).max)); + vm.warp(timestamp); + vm.prank(migrator); + tierRegistry.migrate(); + + timestamp = uint40(bound(timestamp, timestamp, type(uint40).max)); + vm.expectRevert(IMigration.AlreadyMigrated.selector); + vm.prank(migrator); + tierRegistry.migrate(); + + assertEq(tierRegistry.isMigrated(), true); + assertEq(tierRegistry.migratedAt(), timestamp); + } + + /*////////////////////////////////////////////////////////////// + ERC20 RESCUE + //////////////////////////////////////////////////////////////*/ + + function testFuzzRescueTokens(uint256 _amount, address to) public { + vm.assume(to != address(0)); + vm.assume(to != address(tierRegistry)); + vm.assume(to != address(tokenSource)); + uint256 amount = bound(_amount, 1, token.totalSupply()); + + vm.prank(tokenSource); + token.transfer(address(tierRegistry), amount); + + assertEq(token.balanceOf(to), 0); + + vm.prank(owner); + vm.expectEmit(); + emit SweepToken(address(token), to, amount); + tierRegistry.sweepToken(address(token), to); + + assertEq(token.balanceOf(to), amount); + } + + function testFuzzOnlyOwnerCanRescueTokens(address caller, address to) public { + vm.assume(to != address(0)); + vm.assume(caller != owner); + + vm.prank(caller); + vm.expectRevert("Ownable: caller is not the owner"); + tierRegistry.sweepToken(address(token), to); + } + /*////////////////////////////////////////////////////////////// HELPERS //////////////////////////////////////////////////////////////*/ @@ -734,6 +1084,17 @@ contract TierRegistryTest is TierRegistryTestSuite { return tier; } + function _batchCreditTier(uint256 tier, uint256[] memory fids, uint256 numDays, address caller) public { + // Expect emitted events + for (uint256 i; i < fids.length; ++i) { + vm.expectEmit(); + emit PurchasedTier(fids[i], tier, numDays, caller); + } + + vm.prank(caller); + tierRegistry.batchCreditTier(tier, fids, numDays); + } + function _batchPurchaseTier(uint256 tier, uint256[] memory fids, uint256[] memory forDays, address payer) public { uint256 totalTime; for (uint256 i; i < fids.length; ++i) { diff --git a/test/TierRegistry/TierRegistryTestSuite.sol b/test/TierRegistry/TierRegistryTestSuite.sol index 1fed7080..a8814536 100644 --- a/test/TierRegistry/TierRegistryTestSuite.sol +++ b/test/TierRegistry/TierRegistryTestSuite.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.21; +pragma solidity ^0.8.21; import {TestSuiteSetup} from "../TestSuiteSetup.sol"; import "openzeppelin/contracts/token/ERC20/ERC20.sol"; @@ -31,7 +31,7 @@ abstract contract TierRegistryTestSuite is TestSuiteSetup { vm.warp(DEPLOYED_AT); - tierRegistry = new TierRegistry(owner); + tierRegistry = new TierRegistry(migrator, owner); vm.prank(owner); tierRegistry.unpause();