From 69560ff91c1239e21231e286e68c9461c1c5d4f7 Mon Sep 17 00:00:00 2001 From: rizzzhul Date: Thu, 30 Oct 2025 21:33:31 +0530 Subject: [PATCH 1/4] feat(accesscontrol): add external setRoleAdmin and grantRoleBatch/revokeRoleBatch --- .gas-snapshot | 366 ++++++++++++++++++ .../AccessControl/AccessControlFacet.sol | 68 ++++ .../AccessControl/AccessControlFacet.t.sol | 197 ++++++++++ 3 files changed, 631 insertions(+) create mode 100644 .gas-snapshot diff --git a/.gas-snapshot b/.gas-snapshot new file mode 100644 index 00000000..5a08a454 --- /dev/null +++ b/.gas-snapshot @@ -0,0 +1,366 @@ +AccessControlFacetTest:testFuzz_GrantRole_OnlyAdminCanGrant(address,address) (runs: 256, μ: 16490, ~: 16490) +AccessControlFacetTest:testFuzz_HasRole_ConsistentAcrossMultipleRoles(address) (runs: 256, μ: 273182, ~: 273168) +AccessControlFacetTest:testFuzz_RenounceRole_OnlyAccountCanRenounce(address,address) (runs: 256, μ: 33078, ~: 33078) +AccessControlFacetTest:testFuzz_RevokeRole_OnlyAdminCanRevoke(address,address) (runs: 256, μ: 39580, ~: 39580) +AccessControlFacetTest:testFuzz_RoleAdminHierarchy(bytes32,bytes32,bytes32) (runs: 256, μ: 152817, ~: 152817) +AccessControlFacetTest:test_ComplexRoleHierarchy_CannotGrantWithoutProperAdmin() (gas: 63180) +AccessControlFacetTest:test_ComplexRoleHierarchy_GrantingThroughHierarchy() (gas: 147528) +AccessControlFacetTest:test_ComplexRoleHierarchy_Setup() (gas: 55011) +AccessControlFacetTest:test_DelegatedAdminCanExerciseAdminPowers() (gas: 86120) +AccessControlFacetTest:test_EdgeCase_CircularRoleAdminHierarchy() (gas: 130964) +AccessControlFacetTest:test_EdgeCase_GrantAndRevokeInSameBlock() (gas: 33556) +AccessControlFacetTest:test_EdgeCase_MultipleOperationsOnSameRole() (gas: 87511) +AccessControlFacetTest:test_EdgeCase_RoleAdminOfItself() (gas: 85068) +AccessControlFacetTest:test_GetRoleAdmin_DefaultAdminRoleAdminIsItself() (gas: 7754) +AccessControlFacetTest:test_GetRoleAdmin_ReturnsCorrectAdminAfterChange() (gas: 28667) +AccessControlFacetTest:test_GetRoleAdmin_ReturnsDefaultAdminForNewRole() (gas: 7742) +AccessControlFacetTest:test_GrantRoleBatch_SkipsAlreadyGrantedWithoutExtraEvents() (gas: 108119) +AccessControlFacetTest:test_GrantRoleBatch_SucceedsAndEmitsPerNewGrant() (gas: 108483) +AccessControlFacetTest:test_GrantRoleBatch_SucceedsWithEmptyArray() (gas: 15407) +AccessControlFacetTest:test_GrantRole_CanGrantToSelf() (gas: 40898) +AccessControlFacetTest:test_GrantRole_CanGrantToZeroAddress() (gas: 42959) +AccessControlFacetTest:test_GrantRole_DoesNotEmitEventWhenAlreadyGranted() (gas: 45133) +AccessControlFacetTest:test_GrantRole_SucceedsWithCustomRoleAdmin() (gas: 87609) +AccessControlFacetTest:test_GrantRole_SucceedsWithDefaultAdmin() (gas: 45467) +AccessControlFacetTest:test_HasRole_HandlesMultipleAccountsPerRole() (gas: 101690) +AccessControlFacetTest:test_HasRole_HandlesMultipleRolesPerAccount() (gas: 105051) +AccessControlFacetTest:test_HasRole_ReturnsCorrectInitialState() (gas: 15476) +AccessControlFacetTest:test_HasRole_ReturnsFalseForNonGrantedRole() (gas: 10101) +AccessControlFacetTest:test_HasRole_ReturnsTrueForGrantedRole() (gas: 42909) +AccessControlFacetTest:test_RenounceRole_CanRenounceDefaultAdminRole() (gas: 16003) +AccessControlFacetTest:test_RenounceRole_CanRenounceMultipleRoles() (gas: 89596) +AccessControlFacetTest:test_RenounceRole_DoesNotEmitEventWhenNotGranted() (gas: 14401) +AccessControlFacetTest:test_RenounceRole_SucceedsForOwnRole() (gas: 36429) +AccessControlFacetTest:test_RequireRole_PassesWhenAccountHasRole() (gas: 42851) +AccessControlFacetTest:test_RevertWhen_GrantRoleBatch_CallerIsNotAdmin() (gas: 18936) +AccessControlFacetTest:test_RevertWhen_GrantRole_CallerIsNotAdmin() (gas: 18034) +AccessControlFacetTest:test_RevertWhen_GrantRole_CallerIsNotCustomAdmin() (gas: 38966) +AccessControlFacetTest:test_RevertWhen_RenounceRole_AdminCannotRenounceForOthers() (gas: 44092) +AccessControlFacetTest:test_RevertWhen_RenounceRole_CallerIsNotAccount() (gas: 36991) +AccessControlFacetTest:test_RevertWhen_RequireRole_AccountDoesNotHaveRole() (gas: 13349) +AccessControlFacetTest:test_RevertWhen_RequireRole_ZeroAddressDoesNotHaveRole() (gas: 13380) +AccessControlFacetTest:test_RevertWhen_RevokeRoleBatch_CallerIsNotAdmin() (gas: 48947) +AccessControlFacetTest:test_RevertWhen_RevokeRole_CallerIsNotAdmin() (gas: 39269) +AccessControlFacetTest:test_RevertWhen_RevokeRole_CallerIsNotCustomAdmin() (gas: 62190) +AccessControlFacetTest:test_RevertWhen_SetRoleAdmin_CallerIsNotCurrentAdmin() (gas: 36792) +AccessControlFacetTest:test_RevokeRoleBatch_SkipsNotGrantedWithoutExtraEvents() (gas: 46668) +AccessControlFacetTest:test_RevokeRoleBatch_SucceedsAndEmitsPerRevocation() (gas: 92779) +AccessControlFacetTest:test_RevokeRoleBatch_SucceedsWithEmptyArray() (gas: 15407) +AccessControlFacetTest:test_RevokeRole_CanRevokeFromZeroAddress() (gas: 34852) +AccessControlFacetTest:test_RevokeRole_DoesNotEmitEventWhenNotGranted() (gas: 20806) +AccessControlFacetTest:test_RevokeRole_SucceedsWithCustomRoleAdmin() (gas: 68989) +AccessControlFacetTest:test_RevokeRole_SucceedsWithDefaultAdmin() (gas: 36776) +AccessControlFacetTest:test_SetRoleAdmin_SucceedsWhenCallerIsCurrentAdmin() (gas: 40263) +AccessControlFacetTest:test_StorageConsistency_HasRoleMatchesStorage() (gas: 44317) +AccessControlFacetTest:test_StorageConsistency_RoleAdminMatchesStorage() (gas: 29700) +AccessControlFacetTest:test_StorageSlot_UsesCorrectPosition() (gas: 5594) +ERC20FacetTest:testFuzz_Approve(address,uint256) (runs: 256, μ: 36680, ~: 36758) +ERC20FacetTest:testFuzz_Burn(uint256) (runs: 256, μ: 25102, ~: 25212) +ERC20FacetTest:testFuzz_BurnFrom(uint256,uint256) (runs: 256, μ: 55648, ~: 55692) +ERC20FacetTest:testFuzz_Permit(uint256,address,uint256,uint256) (runs: 256, μ: 68150, ~: 68306) +ERC20FacetTest:testFuzz_Transfer(address,uint256) (runs: 256, μ: 43106, ~: 43373) +ERC20FacetTest:testFuzz_TransferFrom(uint256,uint256) (runs: 256, μ: 75285, ~: 75463) +ERC20FacetTest:test_Approve() (gas: 40950) +ERC20FacetTest:test_Approve_ReturnsTrue() (gas: 36997) +ERC20FacetTest:test_Approve_UpdateExisting() (gas: 41917) +ERC20FacetTest:test_Approve_ZeroAmount() (gas: 29363) +ERC20FacetTest:test_BalanceOf() (gas: 15161) +ERC20FacetTest:test_Burn() (gas: 27147) +ERC20FacetTest:test_BurnFrom() (gas: 41514) +ERC20FacetTest:test_BurnFrom_PartialAllowance() (gas: 54892) +ERC20FacetTest:test_BurnFrom_UnlimitedAllowance() (gas: 62794) +ERC20FacetTest:test_BurnFrom_UnlimitedAllowance_MultipleBurns() (gas: 106736) +ERC20FacetTest:test_Burn_EntireBalance() (gas: 15493) +ERC20FacetTest:test_DOMAIN_SEPARATOR() (gas: 8483) +ERC20FacetTest:test_DOMAIN_SEPARATOR_ConsistentWithinSameChain() (gas: 9795) +ERC20FacetTest:test_DOMAIN_SEPARATOR_RecalculatesAfterFork() (gas: 13283) +ERC20FacetTest:test_Decimals() (gas: 7742) +ERC20FacetTest:test_Name() (gas: 12046) +ERC20FacetTest:test_Nonces() (gas: 15226) +ERC20FacetTest:test_Permit() (gas: 71405) +ERC20FacetTest:test_Permit_IncreasesNonce() (gas: 92681) +ERC20FacetTest:test_Permit_MaxValue() (gas: 69353) +ERC20FacetTest:test_Permit_MultipleDifferentSpenders() (gas: 143598) +ERC20FacetTest:test_Permit_OverwritesExistingAllowance() (gas: 103107) +ERC20FacetTest:test_Permit_ThenTransferFrom() (gas: 130371) +ERC20FacetTest:test_Permit_ZeroValue() (gas: 49439) +ERC20FacetTest:test_RevertWhen_ApproveZeroAddressSpender() (gas: 11323) +ERC20FacetTest:test_RevertWhen_BurnFromInsufficientAllowance() (gas: 39533) +ERC20FacetTest:test_RevertWhen_BurnFromInsufficientBalance() (gas: 41856) +ERC20FacetTest:test_RevertWhen_BurnFromNoAllowance() (gas: 15913) +ERC20FacetTest:test_RevertWhen_BurnFromZeroBalance() (gas: 13557) +ERC20FacetTest:test_RevertWhen_BurnInsufficientBalance() (gas: 13639) +ERC20FacetTest:test_RevertWhen_PermitExpired() (gas: 16924) +ERC20FacetTest:test_RevertWhen_PermitInvalidSignature() (gas: 23578) +ERC20FacetTest:test_RevertWhen_PermitMalformedSignature() (gas: 41873) +ERC20FacetTest:test_RevertWhen_PermitReplay() (gas: 73990) +ERC20FacetTest:test_RevertWhen_PermitWrongNonce() (gas: 23550) +ERC20FacetTest:test_RevertWhen_PermitZeroAddressSpender() (gas: 14196) +ERC20FacetTest:test_RevertWhen_TransferFromInsufficientAllowance() (gas: 41816) +ERC20FacetTest:test_RevertWhen_TransferFromInsufficientBalance() (gas: 44096) +ERC20FacetTest:test_RevertWhen_TransferFromNoAllowance() (gas: 18165) +ERC20FacetTest:test_RevertWhen_TransferFromZeroAddressReceiver() (gas: 39183) +ERC20FacetTest:test_RevertWhen_TransferFromZeroAddressSender() (gas: 11086) +ERC20FacetTest:test_RevertWhen_TransferFromZeroBalance() (gas: 15856) +ERC20FacetTest:test_RevertWhen_TransferInsufficientBalance() (gas: 15968) +ERC20FacetTest:test_RevertWhen_TransferOverflowsRecipient() (gas: 48680) +ERC20FacetTest:test_RevertWhen_TransferToZeroAddress() (gas: 11333) +ERC20FacetTest:test_Symbol() (gas: 12053) +ERC20FacetTest:test_TotalSupply() (gas: 7747) +ERC20FacetTest:test_Transfer() (gas: 47044) +ERC20FacetTest:test_TransferFrom() (gas: 57488) +ERC20FacetTest:test_TransferFrom_PartialAllowance() (gas: 74662) +ERC20FacetTest:test_TransferFrom_ReturnsTrue() (gas: 52336) +ERC20FacetTest:test_TransferFrom_UnlimitedAllowance() (gas: 83239) +ERC20FacetTest:test_TransferFrom_UnlimitedAllowance_MultipleTransfers() (gas: 131174) +ERC20FacetTest:test_Transfer_EntireBalance() (gas: 39722) +ERC20FacetTest:test_Transfer_ReturnsTrue() (gas: 42211) +ERC20FacetTest:test_Transfer_ToSelf() (gas: 16589) +ERC20FacetTest:test_Transfer_ZeroAmount() (gas: 21811) +LibAccessControlTest:testFuzz_GrantRole_AlwaysReturnsCorrectBool(address,bytes32) (runs: 256, μ: 37917, ~: 37917) +LibAccessControlTest:testFuzz_HasRole_ConsistentWithStorage(address,bytes32,bool) (runs: 256, μ: 20369, ~: 30767) +LibAccessControlTest:testFuzz_MultipleRolesPerAccount(address) (runs: 256, μ: 128028, ~: 128014) +LibAccessControlTest:testFuzz_RevokeRole_AlwaysReturnsCorrectBool(address,bytes32) (runs: 256, μ: 29935, ~: 29894) +LibAccessControlTest:testFuzz_SetRoleAdmin_AlwaysUpdatesCorrectly(bytes32,bytes32) (runs: 256, μ: 30755, ~: 30755) +LibAccessControlTest:test_DefaultAdminRole_IsZeroBytes() (gas: 5533) +LibAccessControlTest:test_EdgeCase_CircularRoleAdminHierarchy() (gas: 82403) +LibAccessControlTest:test_EdgeCase_GrantAndRevokeMultipleTimes() (gas: 53939) +LibAccessControlTest:test_EdgeCase_RoleAdminOfItself() (gas: 30615) +LibAccessControlTest:test_GetStorage_ReturnsCorrectInitialState() (gas: 11563) +LibAccessControlTest:test_GrantRole_CanGrantToZeroAddress() (gas: 36841) +LibAccessControlTest:test_GrantRole_DoesNotEmitEventWhenAlreadyGranted() (gas: 37355) +LibAccessControlTest:test_GrantRole_EmitsRoleGrantedEvent() (gas: 37912) +LibAccessControlTest:test_GrantRole_GrantsRoleToAccount() (gas: 36783) +LibAccessControlTest:test_GrantRole_MultipleRolesToSameAccount() (gas: 91183) +LibAccessControlTest:test_GrantRole_ReturnsFalseWhenAlreadyGranted() (gas: 38733) +LibAccessControlTest:test_GrantRole_SameRoleToMultipleAccounts() (gas: 95204) +LibAccessControlTest:test_HasRole_HandlesMultipleAccountsPerRole() (gas: 84698) +LibAccessControlTest:test_HasRole_HandlesMultipleRolesPerAccount() (gas: 84130) +LibAccessControlTest:test_HasRole_ReturnsFalseForNonGrantedRole() (gas: 10150) +LibAccessControlTest:test_HasRole_ReturnsFalseForZeroAddress() (gas: 10177) +LibAccessControlTest:test_HasRole_ReturnsTrueForGrantedRole() (gas: 31384) +LibAccessControlTest:test_RequireRole_PassesWhenAccountHasRole() (gas: 31235) +LibAccessControlTest:test_RevertWhen_RequireRole_AccountDoesNotHaveRole() (gas: 13380) +LibAccessControlTest:test_RevertWhen_RequireRole_ZeroAddressDoesNotHaveRole() (gas: 13389) +LibAccessControlTest:test_RevokeRole_DoesNotEmitEventWhenNotGranted() (gas: 13266) +LibAccessControlTest:test_RevokeRole_EmitsRoleRevokedEvent() (gas: 27126) +LibAccessControlTest:test_RevokeRole_OnlyRevokesFromSpecificAccount() (gas: 71490) +LibAccessControlTest:test_RevokeRole_OnlyRevokesSpecificRole() (gas: 67446) +LibAccessControlTest:test_RevokeRole_ReturnsFalseWhenNotGranted() (gas: 14632) +LibAccessControlTest:test_RevokeRole_RevokesRoleFromAccount() (gas: 27432) +LibAccessControlTest:test_SetRoleAdmin_CanSetToDefaultAdminRole() (gas: 10698) +LibAccessControlTest:test_SetRoleAdmin_CanSetToSameRole() (gas: 30660) +LibAccessControlTest:test_SetRoleAdmin_EmitsRoleAdminChangedEvent() (gas: 34466) +LibAccessControlTest:test_SetRoleAdmin_MultipleChanges() (gas: 26690) +LibAccessControlTest:test_SetRoleAdmin_UpdatesAdminRole() (gas: 30613) +LibAccessControlTest:test_StorageSlot_UsesCorrectPosition() (gas: 37851) +LibERC20Test:testFuzz_Approve(address,uint256) (runs: 256, μ: 36579, ~: 36657) +LibERC20Test:testFuzz_Burn(address,uint256,uint256) (runs: 256, μ: 61290, ~: 61290) +LibERC20Test:testFuzz_Mint(address,uint256) (runs: 256, μ: 57241, ~: 57397) +LibERC20Test:testFuzz_Transfer(uint256,uint256) (runs: 256, μ: 87244, ~: 87866) +LibERC20Test:testFuzz_TransferFrom(uint256,uint256,uint256) (runs: 256, μ: 117472, ~: 118250) +LibERC20Test:test_Approve() (gas: 40750) +LibERC20Test:test_ApproveTransferFromBurn_Flow() (gas: 121167) +LibERC20Test:test_Approve_ToZero() (gas: 29179) +LibERC20Test:test_Approve_UpdateExisting() (gas: 41764) +LibERC20Test:test_Burn() (gas: 65061) +LibERC20Test:test_Burn_EntireBalance() (gas: 43463) +LibERC20Test:test_Decimals() (gas: 7773) +LibERC20Test:test_InitialTotalSupply() (gas: 7613) +LibERC20Test:test_Mint() (gas: 61028) +LibERC20Test:test_MintTransferBurn_Flow() (gas: 121324) +LibERC20Test:test_Mint_Multiple() (gas: 88284) +LibERC20Test:test_Name() (gas: 11988) +LibERC20Test:test_RevertWhen_ApproveZeroAddressSpender() (gas: 11320) +LibERC20Test:test_RevertWhen_BurnFromZeroAddress() (gas: 8824) +LibERC20Test:test_RevertWhen_BurnInsufficientBalance() (gas: 58655) +LibERC20Test:test_RevertWhen_BurnZeroBalance() (gas: 13369) +LibERC20Test:test_RevertWhen_MintOverflowsRecipient() (gas: 58179) +LibERC20Test:test_RevertWhen_MintToZeroAddress() (gas: 8853) +LibERC20Test:test_RevertWhen_TransferFromInsufficientAllowance() (gas: 89070) +LibERC20Test:test_RevertWhen_TransferFromInsufficientBalance() (gas: 89300) +LibERC20Test:test_RevertWhen_TransferFromNoAllowance() (gas: 65496) +LibERC20Test:test_RevertWhen_TransferFromZeroAddressReceiver() (gas: 86436) +LibERC20Test:test_RevertWhen_TransferFromZeroAddressSender() (gas: 11045) +LibERC20Test:test_RevertWhen_TransferInsufficientBalance() (gas: 61201) +LibERC20Test:test_RevertWhen_TransferOverflowsRecipient() (gas: 43388) +LibERC20Test:test_RevertWhen_TransferToZeroAddress() (gas: 58629) +LibERC20Test:test_Symbol() (gas: 12016) +LibERC20Test:test_Transfer() (gas: 89379) +LibERC20Test:test_TransferFrom() (gas: 99387) +LibERC20Test:test_TransferFrom_PartialAllowance() (gas: 116988) +LibERC20Test:test_Transfer_ToSelf() (gas: 61846) +LibERC20Test:test_Transfer_ZeroAmount() (gas: 67036) +LibOwnerTest:testFuzz_MultipleTransfers(address,address,address) (runs: 256, μ: 27616, ~: 27635) +LibOwnerTest:testFuzz_RequireOwner(address) (runs: 256, μ: 13130, ~: 13130) +LibOwnerTest:testFuzz_RevertWhen_RenouncedOwnerTransfers(address) (runs: 256, μ: 17478, ~: 17478) +LibOwnerTest:testFuzz_TransferOwnership(address) (runs: 256, μ: 18438, ~: 18457) +LibOwnerTest:test_Events_CorrectPreviousOwner() (gas: 28903) +LibOwnerTest:test_Events_RenounceEmitsZeroAddress() (gas: 16662) +LibOwnerTest:test_GetStorage_ReturnsCorrectOwner() (gas: 11048) +LibOwnerTest:test_LibraryDoesNotCheckMsgSender() (gas: 20497) +LibOwnerTest:test_MultipleTransfers() (gas: 33392) +LibOwnerTest:test_Owner_ReturnsCurrentOwner() (gas: 21710) +LibOwnerTest:test_Owner_ReturnsZeroAfterRenounce() (gas: 15698) +LibOwnerTest:test_RenounceOwnership_EmitsCorrectEvent() (gas: 15913) +LibOwnerTest:test_RenounceOwnership_PermanentlyDisablesTransfers() (gas: 19078) +LibOwnerTest:test_RenounceOwnership_SetsOwnerToZero() (gas: 10456) +LibOwnerTest:test_RequireOwner_PassesForOwner() (gas: 12557) +LibOwnerTest:test_RevertWhen_RequireOwner_CalledByNonOwner() (gas: 12928) +LibOwnerTest:test_RevertWhen_TransferOwnership_FromRenouncedOwner() (gas: 14720) +LibOwnerTest:test_StorageSlot_UsesCorrectPosition() (gas: 21232) +LibOwnerTest:test_TransferOwnership_AllowsTransferToSelf() (gas: 15676) +LibOwnerTest:test_TransferOwnership_AllowsTransferToZeroAddress() (gas: 15675) +LibOwnerTest:test_TransferOwnership_EmitsOwnershipTransferredEvent() (gas: 21462) +LibOwnerTest:test_TransferOwnership_UpdatesOwner() (gas: 20464) +LibOwnerTwoStepsTest:testFuzz_AcceptOwnership(address) (runs: 256, μ: 33371, ~: 33357) +LibOwnerTwoStepsTest:testFuzz_AcceptOwnership_AnyCaller(address) (runs: 256, μ: 34861, ~: 34846) +LibOwnerTwoStepsTest:testFuzz_SequentialTransfers(address,address,address) (runs: 256, μ: 75001, ~: 74954) +LibOwnerTwoStepsTest:testFuzz_TransferOwnership(address) (runs: 256, μ: 38571, ~: 38805) +LibOwnerTwoStepsTest:testFuzz_TransferOwnership_AnyCaller(address,address) (runs: 256, μ: 38758, ~: 38758) +LibOwnerTwoStepsTest:test_AcceptOwnership_ClearsPendingOwner() (gas: 33939) +LibOwnerTwoStepsTest:test_AcceptOwnership_CompletesTransfer() (gas: 34892) +LibOwnerTwoStepsTest:test_AcceptOwnership_CurrentOwnerCanCall() (gas: 34926) +LibOwnerTwoStepsTest:test_AcceptOwnership_EmitsOwnershipTransferredEvent() (gas: 33102) +LibOwnerTwoStepsTest:test_AcceptOwnership_LibraryAllowsAnyCaller() (gas: 36519) +LibOwnerTwoStepsTest:test_AcceptOwnership_NoPendingOwner_SetsOwnerToZero() (gas: 20121) +LibOwnerTwoStepsTest:test_CancelPendingTransfer() (gas: 39450) +LibOwnerTwoStepsTest:test_GetStorage_ReturnsCorrectOwner() (gas: 11094) +LibOwnerTwoStepsTest:test_GetStorage_ReturnsCorrectPendingOwner() (gas: 45130) +LibOwnerTwoStepsTest:test_MultiplePendingChanges_OnlyLastOneMatters() (gas: 45801) +LibOwnerTwoStepsTest:test_Owner_ReturnsCurrentOwner() (gas: 9916) +LibOwnerTwoStepsTest:test_PendingOwner_ReturnsCurrentPendingOwner() (gas: 42827) +LibOwnerTwoStepsTest:test_RenounceOwnership_CannotBeCompleted() (gas: 20945) +LibOwnerTwoStepsTest:test_RenounceOwnership_PreventsNewTransfersAfterForceRenounce() (gas: 17033) +LibOwnerTwoStepsTest:test_RevertWhen_TransferOwnership_FromRenouncedOwner() (gas: 17021) +LibOwnerTwoStepsTest:test_SequentialTransfers() (gas: 79766) +LibOwnerTwoStepsTest:test_StorageCollision_DocumentedBug() (gas: 479) +LibOwnerTwoStepsTest:test_StorageSlot_CurrentlyCollides() (gas: 584) +LibOwnerTwoStepsTest:test_StorageSlot_UsesCorrectPosition() (gas: 39997) +LibOwnerTwoStepsTest:test_TransferOwnership_AllowsTransferToZeroAddress() (gas: 19768) +LibOwnerTwoStepsTest:test_TransferOwnership_CanUpdatePendingOwner() (gas: 46154) +LibOwnerTwoStepsTest:test_TransferOwnership_EmitsOwnershipTransferStartedEvent() (gas: 40612) +LibOwnerTwoStepsTest:test_TransferOwnership_FromPendingOwner_Allowed() (gas: 47376) +LibOwnerTwoStepsTest:test_TransferOwnership_LibraryDoesNotCheckCaller() (gas: 40857) +LibOwnerTwoStepsTest:test_TransferOwnership_SetsPendingOwner() (gas: 40826) +LibOwnerTwoStepsTest:test_TransferToSelf() (gas: 29480) +LibRoyaltyTest:testFuzz_ResetTokenRoyalty(uint256,uint96) (runs: 256, μ: 24792, ~: 24806) +LibRoyaltyTest:testFuzz_RoyaltyInfo_WithTokenRoyalty(uint256,uint96,uint256) (runs: 256, μ: 35533, ~: 35533) +LibRoyaltyTest:testFuzz_RoyaltyInfo_WithValidFee(uint96,uint256) (runs: 256, μ: 37533, ~: 37533) +LibRoyaltyTest:testFuzz_SetDefaultRoyalty(address,uint96) (runs: 256, μ: 33455, ~: 33455) +LibRoyaltyTest:testFuzz_SetTokenRoyalty(uint256,address,uint96) (runs: 256, μ: 33761, ~: 33761) +LibRoyaltyTest:test_ComplexRoyaltyFlow() (gas: 71380) +LibRoyaltyTest:test_DeleteDefaultRoyalty() (gas: 22156) +LibRoyaltyTest:test_DeleteDefaultRoyalty_NoEffectOnTokenRoyalty() (gas: 42694) +LibRoyaltyTest:test_DeleteDefaultRoyalty_RoyaltyInfoReturnsZero() (gas: 23602) +LibRoyaltyTest:test_ResetTokenRoyalty() (gas: 22455) +LibRoyaltyTest:test_ResetTokenRoyalty_FallsBackToDefault() (gas: 44515) +LibRoyaltyTest:test_ResetTokenRoyalty_MultipleTokens() (gas: 64908) +LibRoyaltyTest:test_RevertWhen_SetDefaultRoyalty_InvalidFee() (gas: 11038) +LibRoyaltyTest:test_RevertWhen_SetDefaultRoyalty_ZeroReceiver() (gas: 8894) +LibRoyaltyTest:test_RevertWhen_SetTokenRoyalty_InvalidFee() (gas: 11190) +LibRoyaltyTest:test_RevertWhen_SetTokenRoyalty_ZeroReceiver() (gas: 9111) +LibRoyaltyTest:test_RoyaltyInfo_100PercentRoyalty() (gas: 34015) +LibRoyaltyTest:test_RoyaltyInfo_10PercentRoyalty() (gas: 34081) +LibRoyaltyTest:test_RoyaltyInfo_50PercentRoyalty() (gas: 34049) +LibRoyaltyTest:test_RoyaltyInfo_5PercentRoyalty() (gas: 34042) +LibRoyaltyTest:test_RoyaltyInfo_AfterResetTokenRoyalty() (gas: 43960) +LibRoyaltyTest:test_RoyaltyInfo_DefaultRoyaltyOnly() (gas: 34189) +LibRoyaltyTest:test_RoyaltyInfo_MultipleTokensDifferentRoyalties() (gas: 88550) +LibRoyaltyTest:test_RoyaltyInfo_NoRoyaltySet() (gas: 10614) +LibRoyaltyTest:test_RoyaltyInfo_TokenSpecificOverridesDefault() (gas: 57337) +LibRoyaltyTest:test_RoyaltyInfo_TokenSpecificRoyalty() (gas: 57380) +LibRoyaltyTest:test_RoyaltyInfo_ZeroRoyaltyPercentage() (gas: 33995) +LibRoyaltyTest:test_RoyaltyInfo_ZeroSalePrice() (gas: 34048) +LibRoyaltyTest:test_SetDefaultRoyalty() (gas: 32288) +LibRoyaltyTest:test_SetDefaultRoyalty_MaxPercentage() (gas: 32256) +LibRoyaltyTest:test_SetDefaultRoyalty_UpdatesExisting() (gas: 35515) +LibRoyaltyTest:test_SetDefaultRoyalty_ZeroPercentage() (gas: 32276) +LibRoyaltyTest:test_SetDefaultThenTokenThenReset() (gas: 45416) +LibRoyaltyTest:test_SetTokenRoyalty() (gas: 32551) +LibRoyaltyTest:test_SetTokenRoyalty_MaxPercentage() (gas: 32607) +LibRoyaltyTest:test_SetTokenRoyalty_MultipleTokens() (gas: 88080) +LibRoyaltyTest:test_SetTokenRoyalty_UpdatesExisting() (gas: 35976) +LibRoyaltyTest:test_SetTokenRoyalty_ZeroPercentage() (gas: 32508) +OwnerFacetTest:testFuzz_RenouncePreventsAllTransfers(address,address) (runs: 256, μ: 16669, ~: 16669) +OwnerFacetTest:testFuzz_RevertWhen_UnauthorizedCaller(address,address) (runs: 256, μ: 13622, ~: 13622) +OwnerFacetTest:testFuzz_SequentialTransfers(address,address,address) (runs: 256, μ: 27574, ~: 27574) +OwnerFacetTest:testFuzz_TransferOwnership(address) (runs: 256, μ: 18265, ~: 18340) +OwnerFacetTest:test_Owner_ReturnsCorrectInitialOwner() (gas: 9820) +OwnerFacetTest:test_Owner_ReturnsZeroWhenRenounced() (gas: 15559) +OwnerFacetTest:test_RenounceOwnership_EmitsEvent() (gas: 16641) +OwnerFacetTest:test_RenounceOwnership_PreventsAllFurtherTransfers() (gas: 22137) +OwnerFacetTest:test_RenounceOwnership_SetsOwnerToZero() (gas: 15536) +OwnerFacetTest:test_RevertWhen_TransferOwnership_CalledByNonOwner() (gas: 13041) +OwnerFacetTest:test_RevertWhen_TransferOwnership_CalledByPreviousOwner() (gas: 23130) +OwnerFacetTest:test_StorageSlot_Consistency() (gas: 21114) +OwnerFacetTest:test_TransferOwnership_EmitsCorrectPreviousOwner() (gas: 28775) +OwnerFacetTest:test_TransferOwnership_EmitsOwnershipTransferredEvent() (gas: 21462) +OwnerFacetTest:test_TransferOwnership_ImmediateTransfer() (gas: 20390) +OwnerFacetTest:test_TransferOwnership_MultipleTransfers() (gas: 33064) +OwnerFacetTest:test_TransferOwnership_ToSelf() (gas: 15535) +OwnerTwoStepsFacetTest:testFuzz_AcceptOwnership(address) (runs: 256, μ: 33453, ~: 33438) +OwnerTwoStepsFacetTest:testFuzz_RenounceOwnership_OnlyOwner(address) (runs: 256, μ: 16277, ~: 16277) +OwnerTwoStepsFacetTest:testFuzz_RenounceWithPendingOwner(address) (runs: 256, μ: 34920, ~: 34905) +OwnerTwoStepsFacetTest:testFuzz_RevertWhen_UnauthorizedAccept(address) (runs: 256, μ: 40785, ~: 40785) +OwnerTwoStepsFacetTest:testFuzz_RevertWhen_UnauthorizedTransfer(address,address) (runs: 256, μ: 13658, ~: 13658) +OwnerTwoStepsFacetTest:testFuzz_StateAfterRenounce(address,address) (runs: 256, μ: 21807, ~: 21807) +OwnerTwoStepsFacetTest:testFuzz_TransferOwnership(address) (runs: 256, μ: 38815, ~: 38815) +OwnerTwoStepsFacetTest:test_AcceptOwnership_ClearsPendingOwner() (gas: 34084) +OwnerTwoStepsFacetTest:test_AcceptOwnership_CompletesTransfer() (gas: 34963) +OwnerTwoStepsFacetTest:test_AcceptOwnership_EmitsOwnershipTransferredEvent() (gas: 33241) +OwnerTwoStepsFacetTest:test_DirectRenounce_vs_TwoStepRenounce() (gas: 41265) +OwnerTwoStepsFacetTest:test_MultiplePendingChanges_OnlyLastOneMatters() (gas: 46144) +OwnerTwoStepsFacetTest:test_Owner_ReturnsCorrectInitialOwner() (gas: 9904) +OwnerTwoStepsFacetTest:test_PendingOwner_InitiallyZero() (gas: 9936) +OwnerTwoStepsFacetTest:test_RenounceOwnership_CannotBeReversed() (gas: 19956) +OwnerTwoStepsFacetTest:test_RenounceOwnership_ClearsPendingOwner() (gas: 35924) +OwnerTwoStepsFacetTest:test_RenounceOwnership_DirectlyRenounces() (gas: 18894) +OwnerTwoStepsFacetTest:test_RenounceOwnership_EmitsOwnershipTransferredEvent() (gas: 18719) +OwnerTwoStepsFacetTest:test_RenounceOwnership_OnlyOwnerCanCall() (gas: 17677) +OwnerTwoStepsFacetTest:test_RenounceOwnership_PreventsAllFutureTransfers() (gas: 24288) +OwnerTwoStepsFacetTest:test_RenounceOwnership_TwoStep() (gas: 20911) +OwnerTwoStepsFacetTest:test_RenounceOwnership_WithPendingTransfer() (gas: 37293) +OwnerTwoStepsFacetTest:test_RevertWhen_AcceptOwnership_CalledByCurrentOwner() (gas: 40269) +OwnerTwoStepsFacetTest:test_RevertWhen_AcceptOwnership_CalledByNonPendingOwner() (gas: 42247) +OwnerTwoStepsFacetTest:test_RevertWhen_AcceptOwnership_NoPendingOwner() (gas: 12984) +OwnerTwoStepsFacetTest:test_RevertWhen_RenounceOwnership_CalledByNonOwner() (gas: 18077) +OwnerTwoStepsFacetTest:test_RevertWhen_RenounceOwnership_CalledByPendingOwner() (gas: 40234) +OwnerTwoStepsFacetTest:test_RevertWhen_TransferOwnership_CalledByNonOwner() (gas: 13120) +OwnerTwoStepsFacetTest:test_RevertWhen_TransferOwnership_CalledByPendingOwner() (gas: 42405) +OwnerTwoStepsFacetTest:test_SequentialTransfers() (gas: 78479) +OwnerTwoStepsFacetTest:test_StorageSlot_Consistency() (gas: 33047) +OwnerTwoStepsFacetTest:test_StorageSlot_PendingOwner() (gas: 40490) +OwnerTwoStepsFacetTest:test_TransferOwnership_CanCancelBySettingToZero() (gas: 32766) +OwnerTwoStepsFacetTest:test_TransferOwnership_CanTransferToZeroAddress() (gas: 19834) +OwnerTwoStepsFacetTest:test_TransferOwnership_CanUpdatePendingOwner() (gas: 46268) +OwnerTwoStepsFacetTest:test_TransferOwnership_EmitsOwnershipTransferStartedEvent() (gas: 40705) +OwnerTwoStepsFacetTest:test_TransferOwnership_OnlyOwnerCanInitiate() (gas: 40855) +OwnerTwoStepsFacetTest:test_TransferToSelf() (gas: 29526) +RoyaltyFacetTest:testFuzz_RoyaltyInfo_WithTokenRoyalty(uint256,uint96,uint256) (runs: 256, μ: 35372, ~: 35372) +RoyaltyFacetTest:testFuzz_RoyaltyInfo_WithValidFee(uint96,uint256) (runs: 256, μ: 37394, ~: 37394) +RoyaltyFacetTest:test_ComplexScenario_MultipleTokensAndDefaults() (gas: 88091) +RoyaltyFacetTest:test_RoyaltyInfo_100PercentRoyalty() (gas: 33857) +RoyaltyFacetTest:test_RoyaltyInfo_10PercentRoyalty() (gas: 33880) +RoyaltyFacetTest:test_RoyaltyInfo_50PercentRoyalty() (gas: 33880) +RoyaltyFacetTest:test_RoyaltyInfo_5PercentRoyalty() (gas: 33902) +RoyaltyFacetTest:test_RoyaltyInfo_DefaultRoyaltyAddress() (gas: 33873) +RoyaltyFacetTest:test_RoyaltyInfo_DefaultRoyaltyOnly() (gas: 34030) +RoyaltyFacetTest:test_RoyaltyInfo_FallsBackWhenTokenRoyaltyNotSet() (gas: 33882) +RoyaltyFacetTest:test_RoyaltyInfo_FractionalRoyalty() (gas: 33903) +RoyaltyFacetTest:test_RoyaltyInfo_LargeSalePrice() (gas: 34006) +RoyaltyFacetTest:test_RoyaltyInfo_MinimalRoyaltyFee() (gas: 33857) +RoyaltyFacetTest:test_RoyaltyInfo_MultipleTokensDifferentRoyalties() (gas: 88083) +RoyaltyFacetTest:test_RoyaltyInfo_NoRoyaltySet() (gas: 10550) +RoyaltyFacetTest:test_RoyaltyInfo_SmallTokenId() (gas: 31870) +RoyaltyFacetTest:test_RoyaltyInfo_TokenSpecificOverridesDefault() (gas: 57117) +RoyaltyFacetTest:test_RoyaltyInfo_TokenSpecificRoyalty() (gas: 31852) +RoyaltyFacetTest:test_RoyaltyInfo_VariousFeePercentages() (gas: 51525) +RoyaltyFacetTest:test_RoyaltyInfo_VariousTokenIds() (gas: 86089) +RoyaltyFacetTest:test_RoyaltyInfo_VeryLargeTokenId() (gas: 31882) +RoyaltyFacetTest:test_RoyaltyInfo_WithMaximumValues() (gas: 33894) +RoyaltyFacetTest:test_RoyaltyInfo_ZeroAddressReceiverReturnsZero() (gas: 10540) +RoyaltyFacetTest:test_RoyaltyInfo_ZeroRoyaltyPercentage() (gas: 33871) +RoyaltyFacetTest:test_RoyaltyInfo_ZeroSalePrice() (gas: 33891) +RoyaltyFacetTest:test_StorageSlot_Consistency() (gas: 33804) +RoyaltyFacetTest:test_StorageSlot_TokenRoyaltyConsistency() (gas: 31798) \ No newline at end of file diff --git a/src/access/AccessControl/AccessControlFacet.sol b/src/access/AccessControl/AccessControlFacet.sol index a80a6afa..7a34bc28 100644 --- a/src/access/AccessControl/AccessControlFacet.sol +++ b/src/access/AccessControl/AccessControlFacet.sol @@ -79,6 +79,24 @@ contract AccessControlFacet { return s.adminRole[_role]; } + /// @notice Sets the admin role for a role. + /// @param _role The role to set the admin for. + /// @param _adminRole The new admin role to set. + /// @dev Emits a {RoleAdminChanged} event. + /// @custom:error AccessControlUnauthorizedAccount If the caller is not the current admin of the role. + function setRoleAdmin(bytes32 _role, bytes32 _adminRole) external { + AccessControlStorage storage s = getStorage(); + bytes32 previousAdminRole = s.adminRole[_role]; + + // Check if the caller is the current admin of the role. + if (!s.hasRole[msg.sender][previousAdminRole]) { + revert AccessControlUnauthorizedAccount(msg.sender, previousAdminRole); + } + + s.adminRole[_role] = _adminRole; + emit RoleAdminChanged(_role, previousAdminRole, _adminRole); + } + /// @notice Grants a role to an account. /// @param _role The role to grant. /// @param _account The account to grant the role to. @@ -121,6 +139,56 @@ contract AccessControlFacet { } } + /// @notice Grants a role to multiple accounts in a single transaction. + /// @param _role The role to grant. + /// @param _accounts The accounts to grant the role to. + /// @dev Emits a {RoleGranted} event for each newly granted account. + /// @custom:error AccessControlUnauthorizedAccount If the caller is not the admin of the role. + function grantRoleBatch(bytes32 _role, address[] calldata _accounts) external { + AccessControlStorage storage s = getStorage(); + bytes32 adminRole = s.adminRole[_role]; + + // Check if the caller is the admin of the role. + if (!s.hasRole[msg.sender][adminRole]) { + revert AccessControlUnauthorizedAccount(msg.sender, adminRole); + } + + uint256 length = _accounts.length; + for (uint256 i = 0; i < length; i++) { + address account = _accounts[i]; + bool _hasRole = s.hasRole[account][_role]; + if (!_hasRole) { + s.hasRole[account][_role] = true; + emit RoleGranted(_role, account, msg.sender); + } + } + } + + /// @notice Revokes a role from multiple accounts in a single transaction. + /// @param _role The role to revoke. + /// @param _accounts The accounts to revoke the role from. + /// @dev Emits a {RoleRevoked} event for each account the role is revoked from. + /// @custom:error AccessControlUnauthorizedAccount If the caller is not the admin of the role. + function revokeRoleBatch(bytes32 _role, address[] calldata _accounts) external { + AccessControlStorage storage s = getStorage(); + bytes32 adminRole = s.adminRole[_role]; + + // Check if the caller is the admin of the role. + if (!s.hasRole[msg.sender][adminRole]) { + revert AccessControlUnauthorizedAccount(msg.sender, adminRole); + } + + uint256 length = _accounts.length; + for (uint256 i = 0; i < length; i++) { + address account = _accounts[i]; + bool _hasRole = s.hasRole[account][_role]; + if (_hasRole) { + s.hasRole[account][_role] = false; + emit RoleRevoked(_role, account, msg.sender); + } + } + } + /// @notice Renounces a role from the caller. /// @param _role The role to renounce. /// @param _account The account to renounce the role from. diff --git a/test/access/AccessControl/AccessControlFacet.t.sol b/test/access/AccessControl/AccessControlFacet.t.sol index eaddc131..f00075b5 100644 --- a/test/access/AccessControl/AccessControlFacet.t.sol +++ b/test/access/AccessControl/AccessControlFacet.t.sol @@ -120,6 +120,203 @@ contract AccessControlFacetTest is Test { assertEq(accessControl.getRoleAdmin(MINTER_ROLE), PAUSER_ROLE); } + // ============================================ + // setRoleAdmin Tests (external) + // ============================================ + + function test_SetRoleAdmin_SucceedsWhenCallerIsCurrentAdmin() public { + // DEFAULT_ADMIN_ROLE is current admin for new roles + vm.expectEmit(true, true, true, true); + emit RoleAdminChanged(MINTER_ROLE, DEFAULT_ADMIN_ROLE, PAUSER_ROLE); + + vm.prank(ADMIN); + accessControl.setRoleAdmin(MINTER_ROLE, PAUSER_ROLE); + + assertEq(accessControl.getRoleAdmin(MINTER_ROLE), PAUSER_ROLE); + } + + function test_RevertWhen_SetRoleAdmin_CallerIsNotCurrentAdmin() public { + // Set current admin to PAUSER_ROLE + accessControl.forceSetRoleAdmin(MINTER_ROLE, PAUSER_ROLE); + + // ADMIN has DEFAULT_ADMIN_ROLE but not PAUSER_ROLE + vm.expectRevert( + abi.encodeWithSelector(AccessControlFacet.AccessControlUnauthorizedAccount.selector, ADMIN, PAUSER_ROLE) + ); + vm.prank(ADMIN); + accessControl.setRoleAdmin(MINTER_ROLE, UPGRADER_ROLE); + } + + // ============================================ + // Batch Grant/Revoke Tests + // ============================================ + + function test_GrantRoleBatch_SucceedsAndEmitsPerNewGrant() public { + address[] memory accounts = new address[](3); + accounts[0] = ALICE; + accounts[1] = BOB; + accounts[2] = CHARLIE; + + vm.startPrank(ADMIN); + // Expect three RoleGranted events + vm.expectEmit(true, true, true, true); + emit RoleGranted(MINTER_ROLE, ALICE, ADMIN); + vm.expectEmit(true, true, true, true); + emit RoleGranted(MINTER_ROLE, BOB, ADMIN); + vm.expectEmit(true, true, true, true); + emit RoleGranted(MINTER_ROLE, CHARLIE, ADMIN); + accessControl.grantRoleBatch(MINTER_ROLE, accounts); + vm.stopPrank(); + + assertTrue(accessControl.hasRole(MINTER_ROLE, ALICE)); + assertTrue(accessControl.hasRole(MINTER_ROLE, BOB)); + assertTrue(accessControl.hasRole(MINTER_ROLE, CHARLIE)); + } + + function test_GrantRoleBatch_SkipsAlreadyGrantedWithoutExtraEvents() public { + // Pre-grant ALICE + vm.prank(ADMIN); + accessControl.grantRole(MINTER_ROLE, ALICE); + + address[] memory accounts = new address[](3); + accounts[0] = ALICE; // already granted + accounts[1] = BOB; + accounts[2] = CHARLIE; + + vm.startPrank(ADMIN); + // Expect only two events for new grants + vm.expectEmit(true, true, true, true); + emit RoleGranted(MINTER_ROLE, BOB, ADMIN); + vm.expectEmit(true, true, true, true); + emit RoleGranted(MINTER_ROLE, CHARLIE, ADMIN); + accessControl.grantRoleBatch(MINTER_ROLE, accounts); + vm.stopPrank(); + + assertTrue(accessControl.hasRole(MINTER_ROLE, ALICE)); + assertTrue(accessControl.hasRole(MINTER_ROLE, BOB)); + assertTrue(accessControl.hasRole(MINTER_ROLE, CHARLIE)); + } + + function test_RevertWhen_GrantRoleBatch_CallerIsNotAdmin() public { + address[] memory accounts = new address[](2); + accounts[0] = ALICE; + accounts[1] = BOB; + + vm.expectRevert( + abi.encodeWithSelector( + AccessControlFacet.AccessControlUnauthorizedAccount.selector, ALICE, DEFAULT_ADMIN_ROLE + ) + ); + vm.prank(ALICE); + accessControl.grantRoleBatch(MINTER_ROLE, accounts); + } + + function test_RevokeRoleBatch_SucceedsAndEmitsPerRevocation() public { + // Setup grants + vm.startPrank(ADMIN); + accessControl.grantRole(MINTER_ROLE, ALICE); + accessControl.grantRole(MINTER_ROLE, BOB); + accessControl.grantRole(MINTER_ROLE, CHARLIE); + vm.stopPrank(); + + address[] memory accounts = new address[](3); + accounts[0] = ALICE; + accounts[1] = BOB; + accounts[2] = CHARLIE; + + vm.startPrank(ADMIN); + vm.expectEmit(true, true, true, true); + emit RoleRevoked(MINTER_ROLE, ALICE, ADMIN); + vm.expectEmit(true, true, true, true); + emit RoleRevoked(MINTER_ROLE, BOB, ADMIN); + vm.expectEmit(true, true, true, true); + emit RoleRevoked(MINTER_ROLE, CHARLIE, ADMIN); + accessControl.revokeRoleBatch(MINTER_ROLE, accounts); + vm.stopPrank(); + + assertFalse(accessControl.hasRole(MINTER_ROLE, ALICE)); + assertFalse(accessControl.hasRole(MINTER_ROLE, BOB)); + assertFalse(accessControl.hasRole(MINTER_ROLE, CHARLIE)); + } + + function test_RevokeRoleBatch_SkipsNotGrantedWithoutExtraEvents() public { + // Only ALICE has the role + vm.prank(ADMIN); + accessControl.grantRole(MINTER_ROLE, ALICE); + + address[] memory accounts = new address[](3); + accounts[0] = ALICE; // granted + accounts[1] = BOB; // not granted + accounts[2] = CHARLIE; // not granted + + vm.startPrank(ADMIN); + vm.expectEmit(true, true, true, true); + emit RoleRevoked(MINTER_ROLE, ALICE, ADMIN); + accessControl.revokeRoleBatch(MINTER_ROLE, accounts); + vm.stopPrank(); + + assertFalse(accessControl.hasRole(MINTER_ROLE, ALICE)); + assertFalse(accessControl.hasRole(MINTER_ROLE, BOB)); + assertFalse(accessControl.hasRole(MINTER_ROLE, CHARLIE)); + } + + function test_RevertWhen_RevokeRoleBatch_CallerIsNotAdmin() public { + // Setup grants + vm.prank(ADMIN); + accessControl.grantRole(MINTER_ROLE, ALICE); + + address[] memory accounts = new address[](1); + accounts[0] = ALICE; + + vm.expectRevert( + abi.encodeWithSelector( + AccessControlFacet.AccessControlUnauthorizedAccount.selector, BOB, DEFAULT_ADMIN_ROLE + ) + ); + vm.prank(BOB); + accessControl.revokeRoleBatch(MINTER_ROLE, accounts); + } + + function test_GrantRoleBatch_SucceedsWithEmptyArray() public { + address[] memory accounts = new address[](0); + + // Should just succeed with no reverts and no events + vm.prank(ADMIN); + accessControl.grantRoleBatch(MINTER_ROLE, accounts); + } + + function test_RevokeRoleBatch_SucceedsWithEmptyArray() public { + address[] memory accounts = new address[](0); + + // Should just succeed with no reverts and no events + vm.prank(ADMIN); + accessControl.revokeRoleBatch(MINTER_ROLE, accounts); + } + + function test_DelegatedAdminCanExerciseAdminPowers() public { + // === Arrange === + vm.startPrank(ADMIN); + accessControl.grantRole(MINTER_ROLE, BOB); + accessControl.grantRole(PAUSER_ROLE, ALICE); + accessControl.setRoleAdmin(MINTER_ROLE, PAUSER_ROLE); + vm.stopPrank(); + + // Assert the setup is correct before acting + assertTrue(accessControl.hasRole(MINTER_ROLE, BOB)); + assertTrue(accessControl.hasRole(PAUSER_ROLE, ALICE)); + + // === Act === + // Expect the event to be emitted + vm.expectEmit(true, true, true, true); + emit RoleRevoked(MINTER_ROLE, BOB, ALICE); + + vm.prank(ALICE); + accessControl.revokeRole(MINTER_ROLE, BOB); + + // === Assert === + assertFalse(accessControl.hasRole(MINTER_ROLE, BOB)); + } + function test_GetRoleAdmin_DefaultAdminRoleAdminIsItself() public view { assertEq(accessControl.getRoleAdmin(DEFAULT_ADMIN_ROLE), DEFAULT_ADMIN_ROLE); } From dbbc36550a3effec22f4126eef97b45a47ede2e2 Mon Sep 17 00:00:00 2001 From: rizzzhul Date: Fri, 31 Oct 2025 08:33:14 +0530 Subject: [PATCH 2/4] .gas-snapshot added to git ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 85198aaa..9928863a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ docs/ # Dotenv file .env +.gas-snapshots \ No newline at end of file From ff05d6a9c90302634d8bf9ffa1cdbcbd0b202bf8 Mon Sep 17 00:00:00 2001 From: rizzzhul Date: Fri, 31 Oct 2025 08:36:54 +0530 Subject: [PATCH 3/4] .gas-snapshot added to git ignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9928863a..30a74b08 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,4 @@ docs/ # Dotenv file .env -.gas-snapshots \ No newline at end of file +.gas-snapshot \ No newline at end of file From f8cf561c54067771a60764a339cc5b0173039222 Mon Sep 17 00:00:00 2001 From: rizzzhul Date: Fri, 31 Oct 2025 08:38:59 +0530 Subject: [PATCH 4/4] .gas-snapshot added to git ignore --- .gas-snapshot | 366 -------------------------------------------------- 1 file changed, 366 deletions(-) delete mode 100644 .gas-snapshot diff --git a/.gas-snapshot b/.gas-snapshot deleted file mode 100644 index 5a08a454..00000000 --- a/.gas-snapshot +++ /dev/null @@ -1,366 +0,0 @@ -AccessControlFacetTest:testFuzz_GrantRole_OnlyAdminCanGrant(address,address) (runs: 256, μ: 16490, ~: 16490) -AccessControlFacetTest:testFuzz_HasRole_ConsistentAcrossMultipleRoles(address) (runs: 256, μ: 273182, ~: 273168) -AccessControlFacetTest:testFuzz_RenounceRole_OnlyAccountCanRenounce(address,address) (runs: 256, μ: 33078, ~: 33078) -AccessControlFacetTest:testFuzz_RevokeRole_OnlyAdminCanRevoke(address,address) (runs: 256, μ: 39580, ~: 39580) -AccessControlFacetTest:testFuzz_RoleAdminHierarchy(bytes32,bytes32,bytes32) (runs: 256, μ: 152817, ~: 152817) -AccessControlFacetTest:test_ComplexRoleHierarchy_CannotGrantWithoutProperAdmin() (gas: 63180) -AccessControlFacetTest:test_ComplexRoleHierarchy_GrantingThroughHierarchy() (gas: 147528) -AccessControlFacetTest:test_ComplexRoleHierarchy_Setup() (gas: 55011) -AccessControlFacetTest:test_DelegatedAdminCanExerciseAdminPowers() (gas: 86120) -AccessControlFacetTest:test_EdgeCase_CircularRoleAdminHierarchy() (gas: 130964) -AccessControlFacetTest:test_EdgeCase_GrantAndRevokeInSameBlock() (gas: 33556) -AccessControlFacetTest:test_EdgeCase_MultipleOperationsOnSameRole() (gas: 87511) -AccessControlFacetTest:test_EdgeCase_RoleAdminOfItself() (gas: 85068) -AccessControlFacetTest:test_GetRoleAdmin_DefaultAdminRoleAdminIsItself() (gas: 7754) -AccessControlFacetTest:test_GetRoleAdmin_ReturnsCorrectAdminAfterChange() (gas: 28667) -AccessControlFacetTest:test_GetRoleAdmin_ReturnsDefaultAdminForNewRole() (gas: 7742) -AccessControlFacetTest:test_GrantRoleBatch_SkipsAlreadyGrantedWithoutExtraEvents() (gas: 108119) -AccessControlFacetTest:test_GrantRoleBatch_SucceedsAndEmitsPerNewGrant() (gas: 108483) -AccessControlFacetTest:test_GrantRoleBatch_SucceedsWithEmptyArray() (gas: 15407) -AccessControlFacetTest:test_GrantRole_CanGrantToSelf() (gas: 40898) -AccessControlFacetTest:test_GrantRole_CanGrantToZeroAddress() (gas: 42959) -AccessControlFacetTest:test_GrantRole_DoesNotEmitEventWhenAlreadyGranted() (gas: 45133) -AccessControlFacetTest:test_GrantRole_SucceedsWithCustomRoleAdmin() (gas: 87609) -AccessControlFacetTest:test_GrantRole_SucceedsWithDefaultAdmin() (gas: 45467) -AccessControlFacetTest:test_HasRole_HandlesMultipleAccountsPerRole() (gas: 101690) -AccessControlFacetTest:test_HasRole_HandlesMultipleRolesPerAccount() (gas: 105051) -AccessControlFacetTest:test_HasRole_ReturnsCorrectInitialState() (gas: 15476) -AccessControlFacetTest:test_HasRole_ReturnsFalseForNonGrantedRole() (gas: 10101) -AccessControlFacetTest:test_HasRole_ReturnsTrueForGrantedRole() (gas: 42909) -AccessControlFacetTest:test_RenounceRole_CanRenounceDefaultAdminRole() (gas: 16003) -AccessControlFacetTest:test_RenounceRole_CanRenounceMultipleRoles() (gas: 89596) -AccessControlFacetTest:test_RenounceRole_DoesNotEmitEventWhenNotGranted() (gas: 14401) -AccessControlFacetTest:test_RenounceRole_SucceedsForOwnRole() (gas: 36429) -AccessControlFacetTest:test_RequireRole_PassesWhenAccountHasRole() (gas: 42851) -AccessControlFacetTest:test_RevertWhen_GrantRoleBatch_CallerIsNotAdmin() (gas: 18936) -AccessControlFacetTest:test_RevertWhen_GrantRole_CallerIsNotAdmin() (gas: 18034) -AccessControlFacetTest:test_RevertWhen_GrantRole_CallerIsNotCustomAdmin() (gas: 38966) -AccessControlFacetTest:test_RevertWhen_RenounceRole_AdminCannotRenounceForOthers() (gas: 44092) -AccessControlFacetTest:test_RevertWhen_RenounceRole_CallerIsNotAccount() (gas: 36991) -AccessControlFacetTest:test_RevertWhen_RequireRole_AccountDoesNotHaveRole() (gas: 13349) -AccessControlFacetTest:test_RevertWhen_RequireRole_ZeroAddressDoesNotHaveRole() (gas: 13380) -AccessControlFacetTest:test_RevertWhen_RevokeRoleBatch_CallerIsNotAdmin() (gas: 48947) -AccessControlFacetTest:test_RevertWhen_RevokeRole_CallerIsNotAdmin() (gas: 39269) -AccessControlFacetTest:test_RevertWhen_RevokeRole_CallerIsNotCustomAdmin() (gas: 62190) -AccessControlFacetTest:test_RevertWhen_SetRoleAdmin_CallerIsNotCurrentAdmin() (gas: 36792) -AccessControlFacetTest:test_RevokeRoleBatch_SkipsNotGrantedWithoutExtraEvents() (gas: 46668) -AccessControlFacetTest:test_RevokeRoleBatch_SucceedsAndEmitsPerRevocation() (gas: 92779) -AccessControlFacetTest:test_RevokeRoleBatch_SucceedsWithEmptyArray() (gas: 15407) -AccessControlFacetTest:test_RevokeRole_CanRevokeFromZeroAddress() (gas: 34852) -AccessControlFacetTest:test_RevokeRole_DoesNotEmitEventWhenNotGranted() (gas: 20806) -AccessControlFacetTest:test_RevokeRole_SucceedsWithCustomRoleAdmin() (gas: 68989) -AccessControlFacetTest:test_RevokeRole_SucceedsWithDefaultAdmin() (gas: 36776) -AccessControlFacetTest:test_SetRoleAdmin_SucceedsWhenCallerIsCurrentAdmin() (gas: 40263) -AccessControlFacetTest:test_StorageConsistency_HasRoleMatchesStorage() (gas: 44317) -AccessControlFacetTest:test_StorageConsistency_RoleAdminMatchesStorage() (gas: 29700) -AccessControlFacetTest:test_StorageSlot_UsesCorrectPosition() (gas: 5594) -ERC20FacetTest:testFuzz_Approve(address,uint256) (runs: 256, μ: 36680, ~: 36758) -ERC20FacetTest:testFuzz_Burn(uint256) (runs: 256, μ: 25102, ~: 25212) -ERC20FacetTest:testFuzz_BurnFrom(uint256,uint256) (runs: 256, μ: 55648, ~: 55692) -ERC20FacetTest:testFuzz_Permit(uint256,address,uint256,uint256) (runs: 256, μ: 68150, ~: 68306) -ERC20FacetTest:testFuzz_Transfer(address,uint256) (runs: 256, μ: 43106, ~: 43373) -ERC20FacetTest:testFuzz_TransferFrom(uint256,uint256) (runs: 256, μ: 75285, ~: 75463) -ERC20FacetTest:test_Approve() (gas: 40950) -ERC20FacetTest:test_Approve_ReturnsTrue() (gas: 36997) -ERC20FacetTest:test_Approve_UpdateExisting() (gas: 41917) -ERC20FacetTest:test_Approve_ZeroAmount() (gas: 29363) -ERC20FacetTest:test_BalanceOf() (gas: 15161) -ERC20FacetTest:test_Burn() (gas: 27147) -ERC20FacetTest:test_BurnFrom() (gas: 41514) -ERC20FacetTest:test_BurnFrom_PartialAllowance() (gas: 54892) -ERC20FacetTest:test_BurnFrom_UnlimitedAllowance() (gas: 62794) -ERC20FacetTest:test_BurnFrom_UnlimitedAllowance_MultipleBurns() (gas: 106736) -ERC20FacetTest:test_Burn_EntireBalance() (gas: 15493) -ERC20FacetTest:test_DOMAIN_SEPARATOR() (gas: 8483) -ERC20FacetTest:test_DOMAIN_SEPARATOR_ConsistentWithinSameChain() (gas: 9795) -ERC20FacetTest:test_DOMAIN_SEPARATOR_RecalculatesAfterFork() (gas: 13283) -ERC20FacetTest:test_Decimals() (gas: 7742) -ERC20FacetTest:test_Name() (gas: 12046) -ERC20FacetTest:test_Nonces() (gas: 15226) -ERC20FacetTest:test_Permit() (gas: 71405) -ERC20FacetTest:test_Permit_IncreasesNonce() (gas: 92681) -ERC20FacetTest:test_Permit_MaxValue() (gas: 69353) -ERC20FacetTest:test_Permit_MultipleDifferentSpenders() (gas: 143598) -ERC20FacetTest:test_Permit_OverwritesExistingAllowance() (gas: 103107) -ERC20FacetTest:test_Permit_ThenTransferFrom() (gas: 130371) -ERC20FacetTest:test_Permit_ZeroValue() (gas: 49439) -ERC20FacetTest:test_RevertWhen_ApproveZeroAddressSpender() (gas: 11323) -ERC20FacetTest:test_RevertWhen_BurnFromInsufficientAllowance() (gas: 39533) -ERC20FacetTest:test_RevertWhen_BurnFromInsufficientBalance() (gas: 41856) -ERC20FacetTest:test_RevertWhen_BurnFromNoAllowance() (gas: 15913) -ERC20FacetTest:test_RevertWhen_BurnFromZeroBalance() (gas: 13557) -ERC20FacetTest:test_RevertWhen_BurnInsufficientBalance() (gas: 13639) -ERC20FacetTest:test_RevertWhen_PermitExpired() (gas: 16924) -ERC20FacetTest:test_RevertWhen_PermitInvalidSignature() (gas: 23578) -ERC20FacetTest:test_RevertWhen_PermitMalformedSignature() (gas: 41873) -ERC20FacetTest:test_RevertWhen_PermitReplay() (gas: 73990) -ERC20FacetTest:test_RevertWhen_PermitWrongNonce() (gas: 23550) -ERC20FacetTest:test_RevertWhen_PermitZeroAddressSpender() (gas: 14196) -ERC20FacetTest:test_RevertWhen_TransferFromInsufficientAllowance() (gas: 41816) -ERC20FacetTest:test_RevertWhen_TransferFromInsufficientBalance() (gas: 44096) -ERC20FacetTest:test_RevertWhen_TransferFromNoAllowance() (gas: 18165) -ERC20FacetTest:test_RevertWhen_TransferFromZeroAddressReceiver() (gas: 39183) -ERC20FacetTest:test_RevertWhen_TransferFromZeroAddressSender() (gas: 11086) -ERC20FacetTest:test_RevertWhen_TransferFromZeroBalance() (gas: 15856) -ERC20FacetTest:test_RevertWhen_TransferInsufficientBalance() (gas: 15968) -ERC20FacetTest:test_RevertWhen_TransferOverflowsRecipient() (gas: 48680) -ERC20FacetTest:test_RevertWhen_TransferToZeroAddress() (gas: 11333) -ERC20FacetTest:test_Symbol() (gas: 12053) -ERC20FacetTest:test_TotalSupply() (gas: 7747) -ERC20FacetTest:test_Transfer() (gas: 47044) -ERC20FacetTest:test_TransferFrom() (gas: 57488) -ERC20FacetTest:test_TransferFrom_PartialAllowance() (gas: 74662) -ERC20FacetTest:test_TransferFrom_ReturnsTrue() (gas: 52336) -ERC20FacetTest:test_TransferFrom_UnlimitedAllowance() (gas: 83239) -ERC20FacetTest:test_TransferFrom_UnlimitedAllowance_MultipleTransfers() (gas: 131174) -ERC20FacetTest:test_Transfer_EntireBalance() (gas: 39722) -ERC20FacetTest:test_Transfer_ReturnsTrue() (gas: 42211) -ERC20FacetTest:test_Transfer_ToSelf() (gas: 16589) -ERC20FacetTest:test_Transfer_ZeroAmount() (gas: 21811) -LibAccessControlTest:testFuzz_GrantRole_AlwaysReturnsCorrectBool(address,bytes32) (runs: 256, μ: 37917, ~: 37917) -LibAccessControlTest:testFuzz_HasRole_ConsistentWithStorage(address,bytes32,bool) (runs: 256, μ: 20369, ~: 30767) -LibAccessControlTest:testFuzz_MultipleRolesPerAccount(address) (runs: 256, μ: 128028, ~: 128014) -LibAccessControlTest:testFuzz_RevokeRole_AlwaysReturnsCorrectBool(address,bytes32) (runs: 256, μ: 29935, ~: 29894) -LibAccessControlTest:testFuzz_SetRoleAdmin_AlwaysUpdatesCorrectly(bytes32,bytes32) (runs: 256, μ: 30755, ~: 30755) -LibAccessControlTest:test_DefaultAdminRole_IsZeroBytes() (gas: 5533) -LibAccessControlTest:test_EdgeCase_CircularRoleAdminHierarchy() (gas: 82403) -LibAccessControlTest:test_EdgeCase_GrantAndRevokeMultipleTimes() (gas: 53939) -LibAccessControlTest:test_EdgeCase_RoleAdminOfItself() (gas: 30615) -LibAccessControlTest:test_GetStorage_ReturnsCorrectInitialState() (gas: 11563) -LibAccessControlTest:test_GrantRole_CanGrantToZeroAddress() (gas: 36841) -LibAccessControlTest:test_GrantRole_DoesNotEmitEventWhenAlreadyGranted() (gas: 37355) -LibAccessControlTest:test_GrantRole_EmitsRoleGrantedEvent() (gas: 37912) -LibAccessControlTest:test_GrantRole_GrantsRoleToAccount() (gas: 36783) -LibAccessControlTest:test_GrantRole_MultipleRolesToSameAccount() (gas: 91183) -LibAccessControlTest:test_GrantRole_ReturnsFalseWhenAlreadyGranted() (gas: 38733) -LibAccessControlTest:test_GrantRole_SameRoleToMultipleAccounts() (gas: 95204) -LibAccessControlTest:test_HasRole_HandlesMultipleAccountsPerRole() (gas: 84698) -LibAccessControlTest:test_HasRole_HandlesMultipleRolesPerAccount() (gas: 84130) -LibAccessControlTest:test_HasRole_ReturnsFalseForNonGrantedRole() (gas: 10150) -LibAccessControlTest:test_HasRole_ReturnsFalseForZeroAddress() (gas: 10177) -LibAccessControlTest:test_HasRole_ReturnsTrueForGrantedRole() (gas: 31384) -LibAccessControlTest:test_RequireRole_PassesWhenAccountHasRole() (gas: 31235) -LibAccessControlTest:test_RevertWhen_RequireRole_AccountDoesNotHaveRole() (gas: 13380) -LibAccessControlTest:test_RevertWhen_RequireRole_ZeroAddressDoesNotHaveRole() (gas: 13389) -LibAccessControlTest:test_RevokeRole_DoesNotEmitEventWhenNotGranted() (gas: 13266) -LibAccessControlTest:test_RevokeRole_EmitsRoleRevokedEvent() (gas: 27126) -LibAccessControlTest:test_RevokeRole_OnlyRevokesFromSpecificAccount() (gas: 71490) -LibAccessControlTest:test_RevokeRole_OnlyRevokesSpecificRole() (gas: 67446) -LibAccessControlTest:test_RevokeRole_ReturnsFalseWhenNotGranted() (gas: 14632) -LibAccessControlTest:test_RevokeRole_RevokesRoleFromAccount() (gas: 27432) -LibAccessControlTest:test_SetRoleAdmin_CanSetToDefaultAdminRole() (gas: 10698) -LibAccessControlTest:test_SetRoleAdmin_CanSetToSameRole() (gas: 30660) -LibAccessControlTest:test_SetRoleAdmin_EmitsRoleAdminChangedEvent() (gas: 34466) -LibAccessControlTest:test_SetRoleAdmin_MultipleChanges() (gas: 26690) -LibAccessControlTest:test_SetRoleAdmin_UpdatesAdminRole() (gas: 30613) -LibAccessControlTest:test_StorageSlot_UsesCorrectPosition() (gas: 37851) -LibERC20Test:testFuzz_Approve(address,uint256) (runs: 256, μ: 36579, ~: 36657) -LibERC20Test:testFuzz_Burn(address,uint256,uint256) (runs: 256, μ: 61290, ~: 61290) -LibERC20Test:testFuzz_Mint(address,uint256) (runs: 256, μ: 57241, ~: 57397) -LibERC20Test:testFuzz_Transfer(uint256,uint256) (runs: 256, μ: 87244, ~: 87866) -LibERC20Test:testFuzz_TransferFrom(uint256,uint256,uint256) (runs: 256, μ: 117472, ~: 118250) -LibERC20Test:test_Approve() (gas: 40750) -LibERC20Test:test_ApproveTransferFromBurn_Flow() (gas: 121167) -LibERC20Test:test_Approve_ToZero() (gas: 29179) -LibERC20Test:test_Approve_UpdateExisting() (gas: 41764) -LibERC20Test:test_Burn() (gas: 65061) -LibERC20Test:test_Burn_EntireBalance() (gas: 43463) -LibERC20Test:test_Decimals() (gas: 7773) -LibERC20Test:test_InitialTotalSupply() (gas: 7613) -LibERC20Test:test_Mint() (gas: 61028) -LibERC20Test:test_MintTransferBurn_Flow() (gas: 121324) -LibERC20Test:test_Mint_Multiple() (gas: 88284) -LibERC20Test:test_Name() (gas: 11988) -LibERC20Test:test_RevertWhen_ApproveZeroAddressSpender() (gas: 11320) -LibERC20Test:test_RevertWhen_BurnFromZeroAddress() (gas: 8824) -LibERC20Test:test_RevertWhen_BurnInsufficientBalance() (gas: 58655) -LibERC20Test:test_RevertWhen_BurnZeroBalance() (gas: 13369) -LibERC20Test:test_RevertWhen_MintOverflowsRecipient() (gas: 58179) -LibERC20Test:test_RevertWhen_MintToZeroAddress() (gas: 8853) -LibERC20Test:test_RevertWhen_TransferFromInsufficientAllowance() (gas: 89070) -LibERC20Test:test_RevertWhen_TransferFromInsufficientBalance() (gas: 89300) -LibERC20Test:test_RevertWhen_TransferFromNoAllowance() (gas: 65496) -LibERC20Test:test_RevertWhen_TransferFromZeroAddressReceiver() (gas: 86436) -LibERC20Test:test_RevertWhen_TransferFromZeroAddressSender() (gas: 11045) -LibERC20Test:test_RevertWhen_TransferInsufficientBalance() (gas: 61201) -LibERC20Test:test_RevertWhen_TransferOverflowsRecipient() (gas: 43388) -LibERC20Test:test_RevertWhen_TransferToZeroAddress() (gas: 58629) -LibERC20Test:test_Symbol() (gas: 12016) -LibERC20Test:test_Transfer() (gas: 89379) -LibERC20Test:test_TransferFrom() (gas: 99387) -LibERC20Test:test_TransferFrom_PartialAllowance() (gas: 116988) -LibERC20Test:test_Transfer_ToSelf() (gas: 61846) -LibERC20Test:test_Transfer_ZeroAmount() (gas: 67036) -LibOwnerTest:testFuzz_MultipleTransfers(address,address,address) (runs: 256, μ: 27616, ~: 27635) -LibOwnerTest:testFuzz_RequireOwner(address) (runs: 256, μ: 13130, ~: 13130) -LibOwnerTest:testFuzz_RevertWhen_RenouncedOwnerTransfers(address) (runs: 256, μ: 17478, ~: 17478) -LibOwnerTest:testFuzz_TransferOwnership(address) (runs: 256, μ: 18438, ~: 18457) -LibOwnerTest:test_Events_CorrectPreviousOwner() (gas: 28903) -LibOwnerTest:test_Events_RenounceEmitsZeroAddress() (gas: 16662) -LibOwnerTest:test_GetStorage_ReturnsCorrectOwner() (gas: 11048) -LibOwnerTest:test_LibraryDoesNotCheckMsgSender() (gas: 20497) -LibOwnerTest:test_MultipleTransfers() (gas: 33392) -LibOwnerTest:test_Owner_ReturnsCurrentOwner() (gas: 21710) -LibOwnerTest:test_Owner_ReturnsZeroAfterRenounce() (gas: 15698) -LibOwnerTest:test_RenounceOwnership_EmitsCorrectEvent() (gas: 15913) -LibOwnerTest:test_RenounceOwnership_PermanentlyDisablesTransfers() (gas: 19078) -LibOwnerTest:test_RenounceOwnership_SetsOwnerToZero() (gas: 10456) -LibOwnerTest:test_RequireOwner_PassesForOwner() (gas: 12557) -LibOwnerTest:test_RevertWhen_RequireOwner_CalledByNonOwner() (gas: 12928) -LibOwnerTest:test_RevertWhen_TransferOwnership_FromRenouncedOwner() (gas: 14720) -LibOwnerTest:test_StorageSlot_UsesCorrectPosition() (gas: 21232) -LibOwnerTest:test_TransferOwnership_AllowsTransferToSelf() (gas: 15676) -LibOwnerTest:test_TransferOwnership_AllowsTransferToZeroAddress() (gas: 15675) -LibOwnerTest:test_TransferOwnership_EmitsOwnershipTransferredEvent() (gas: 21462) -LibOwnerTest:test_TransferOwnership_UpdatesOwner() (gas: 20464) -LibOwnerTwoStepsTest:testFuzz_AcceptOwnership(address) (runs: 256, μ: 33371, ~: 33357) -LibOwnerTwoStepsTest:testFuzz_AcceptOwnership_AnyCaller(address) (runs: 256, μ: 34861, ~: 34846) -LibOwnerTwoStepsTest:testFuzz_SequentialTransfers(address,address,address) (runs: 256, μ: 75001, ~: 74954) -LibOwnerTwoStepsTest:testFuzz_TransferOwnership(address) (runs: 256, μ: 38571, ~: 38805) -LibOwnerTwoStepsTest:testFuzz_TransferOwnership_AnyCaller(address,address) (runs: 256, μ: 38758, ~: 38758) -LibOwnerTwoStepsTest:test_AcceptOwnership_ClearsPendingOwner() (gas: 33939) -LibOwnerTwoStepsTest:test_AcceptOwnership_CompletesTransfer() (gas: 34892) -LibOwnerTwoStepsTest:test_AcceptOwnership_CurrentOwnerCanCall() (gas: 34926) -LibOwnerTwoStepsTest:test_AcceptOwnership_EmitsOwnershipTransferredEvent() (gas: 33102) -LibOwnerTwoStepsTest:test_AcceptOwnership_LibraryAllowsAnyCaller() (gas: 36519) -LibOwnerTwoStepsTest:test_AcceptOwnership_NoPendingOwner_SetsOwnerToZero() (gas: 20121) -LibOwnerTwoStepsTest:test_CancelPendingTransfer() (gas: 39450) -LibOwnerTwoStepsTest:test_GetStorage_ReturnsCorrectOwner() (gas: 11094) -LibOwnerTwoStepsTest:test_GetStorage_ReturnsCorrectPendingOwner() (gas: 45130) -LibOwnerTwoStepsTest:test_MultiplePendingChanges_OnlyLastOneMatters() (gas: 45801) -LibOwnerTwoStepsTest:test_Owner_ReturnsCurrentOwner() (gas: 9916) -LibOwnerTwoStepsTest:test_PendingOwner_ReturnsCurrentPendingOwner() (gas: 42827) -LibOwnerTwoStepsTest:test_RenounceOwnership_CannotBeCompleted() (gas: 20945) -LibOwnerTwoStepsTest:test_RenounceOwnership_PreventsNewTransfersAfterForceRenounce() (gas: 17033) -LibOwnerTwoStepsTest:test_RevertWhen_TransferOwnership_FromRenouncedOwner() (gas: 17021) -LibOwnerTwoStepsTest:test_SequentialTransfers() (gas: 79766) -LibOwnerTwoStepsTest:test_StorageCollision_DocumentedBug() (gas: 479) -LibOwnerTwoStepsTest:test_StorageSlot_CurrentlyCollides() (gas: 584) -LibOwnerTwoStepsTest:test_StorageSlot_UsesCorrectPosition() (gas: 39997) -LibOwnerTwoStepsTest:test_TransferOwnership_AllowsTransferToZeroAddress() (gas: 19768) -LibOwnerTwoStepsTest:test_TransferOwnership_CanUpdatePendingOwner() (gas: 46154) -LibOwnerTwoStepsTest:test_TransferOwnership_EmitsOwnershipTransferStartedEvent() (gas: 40612) -LibOwnerTwoStepsTest:test_TransferOwnership_FromPendingOwner_Allowed() (gas: 47376) -LibOwnerTwoStepsTest:test_TransferOwnership_LibraryDoesNotCheckCaller() (gas: 40857) -LibOwnerTwoStepsTest:test_TransferOwnership_SetsPendingOwner() (gas: 40826) -LibOwnerTwoStepsTest:test_TransferToSelf() (gas: 29480) -LibRoyaltyTest:testFuzz_ResetTokenRoyalty(uint256,uint96) (runs: 256, μ: 24792, ~: 24806) -LibRoyaltyTest:testFuzz_RoyaltyInfo_WithTokenRoyalty(uint256,uint96,uint256) (runs: 256, μ: 35533, ~: 35533) -LibRoyaltyTest:testFuzz_RoyaltyInfo_WithValidFee(uint96,uint256) (runs: 256, μ: 37533, ~: 37533) -LibRoyaltyTest:testFuzz_SetDefaultRoyalty(address,uint96) (runs: 256, μ: 33455, ~: 33455) -LibRoyaltyTest:testFuzz_SetTokenRoyalty(uint256,address,uint96) (runs: 256, μ: 33761, ~: 33761) -LibRoyaltyTest:test_ComplexRoyaltyFlow() (gas: 71380) -LibRoyaltyTest:test_DeleteDefaultRoyalty() (gas: 22156) -LibRoyaltyTest:test_DeleteDefaultRoyalty_NoEffectOnTokenRoyalty() (gas: 42694) -LibRoyaltyTest:test_DeleteDefaultRoyalty_RoyaltyInfoReturnsZero() (gas: 23602) -LibRoyaltyTest:test_ResetTokenRoyalty() (gas: 22455) -LibRoyaltyTest:test_ResetTokenRoyalty_FallsBackToDefault() (gas: 44515) -LibRoyaltyTest:test_ResetTokenRoyalty_MultipleTokens() (gas: 64908) -LibRoyaltyTest:test_RevertWhen_SetDefaultRoyalty_InvalidFee() (gas: 11038) -LibRoyaltyTest:test_RevertWhen_SetDefaultRoyalty_ZeroReceiver() (gas: 8894) -LibRoyaltyTest:test_RevertWhen_SetTokenRoyalty_InvalidFee() (gas: 11190) -LibRoyaltyTest:test_RevertWhen_SetTokenRoyalty_ZeroReceiver() (gas: 9111) -LibRoyaltyTest:test_RoyaltyInfo_100PercentRoyalty() (gas: 34015) -LibRoyaltyTest:test_RoyaltyInfo_10PercentRoyalty() (gas: 34081) -LibRoyaltyTest:test_RoyaltyInfo_50PercentRoyalty() (gas: 34049) -LibRoyaltyTest:test_RoyaltyInfo_5PercentRoyalty() (gas: 34042) -LibRoyaltyTest:test_RoyaltyInfo_AfterResetTokenRoyalty() (gas: 43960) -LibRoyaltyTest:test_RoyaltyInfo_DefaultRoyaltyOnly() (gas: 34189) -LibRoyaltyTest:test_RoyaltyInfo_MultipleTokensDifferentRoyalties() (gas: 88550) -LibRoyaltyTest:test_RoyaltyInfo_NoRoyaltySet() (gas: 10614) -LibRoyaltyTest:test_RoyaltyInfo_TokenSpecificOverridesDefault() (gas: 57337) -LibRoyaltyTest:test_RoyaltyInfo_TokenSpecificRoyalty() (gas: 57380) -LibRoyaltyTest:test_RoyaltyInfo_ZeroRoyaltyPercentage() (gas: 33995) -LibRoyaltyTest:test_RoyaltyInfo_ZeroSalePrice() (gas: 34048) -LibRoyaltyTest:test_SetDefaultRoyalty() (gas: 32288) -LibRoyaltyTest:test_SetDefaultRoyalty_MaxPercentage() (gas: 32256) -LibRoyaltyTest:test_SetDefaultRoyalty_UpdatesExisting() (gas: 35515) -LibRoyaltyTest:test_SetDefaultRoyalty_ZeroPercentage() (gas: 32276) -LibRoyaltyTest:test_SetDefaultThenTokenThenReset() (gas: 45416) -LibRoyaltyTest:test_SetTokenRoyalty() (gas: 32551) -LibRoyaltyTest:test_SetTokenRoyalty_MaxPercentage() (gas: 32607) -LibRoyaltyTest:test_SetTokenRoyalty_MultipleTokens() (gas: 88080) -LibRoyaltyTest:test_SetTokenRoyalty_UpdatesExisting() (gas: 35976) -LibRoyaltyTest:test_SetTokenRoyalty_ZeroPercentage() (gas: 32508) -OwnerFacetTest:testFuzz_RenouncePreventsAllTransfers(address,address) (runs: 256, μ: 16669, ~: 16669) -OwnerFacetTest:testFuzz_RevertWhen_UnauthorizedCaller(address,address) (runs: 256, μ: 13622, ~: 13622) -OwnerFacetTest:testFuzz_SequentialTransfers(address,address,address) (runs: 256, μ: 27574, ~: 27574) -OwnerFacetTest:testFuzz_TransferOwnership(address) (runs: 256, μ: 18265, ~: 18340) -OwnerFacetTest:test_Owner_ReturnsCorrectInitialOwner() (gas: 9820) -OwnerFacetTest:test_Owner_ReturnsZeroWhenRenounced() (gas: 15559) -OwnerFacetTest:test_RenounceOwnership_EmitsEvent() (gas: 16641) -OwnerFacetTest:test_RenounceOwnership_PreventsAllFurtherTransfers() (gas: 22137) -OwnerFacetTest:test_RenounceOwnership_SetsOwnerToZero() (gas: 15536) -OwnerFacetTest:test_RevertWhen_TransferOwnership_CalledByNonOwner() (gas: 13041) -OwnerFacetTest:test_RevertWhen_TransferOwnership_CalledByPreviousOwner() (gas: 23130) -OwnerFacetTest:test_StorageSlot_Consistency() (gas: 21114) -OwnerFacetTest:test_TransferOwnership_EmitsCorrectPreviousOwner() (gas: 28775) -OwnerFacetTest:test_TransferOwnership_EmitsOwnershipTransferredEvent() (gas: 21462) -OwnerFacetTest:test_TransferOwnership_ImmediateTransfer() (gas: 20390) -OwnerFacetTest:test_TransferOwnership_MultipleTransfers() (gas: 33064) -OwnerFacetTest:test_TransferOwnership_ToSelf() (gas: 15535) -OwnerTwoStepsFacetTest:testFuzz_AcceptOwnership(address) (runs: 256, μ: 33453, ~: 33438) -OwnerTwoStepsFacetTest:testFuzz_RenounceOwnership_OnlyOwner(address) (runs: 256, μ: 16277, ~: 16277) -OwnerTwoStepsFacetTest:testFuzz_RenounceWithPendingOwner(address) (runs: 256, μ: 34920, ~: 34905) -OwnerTwoStepsFacetTest:testFuzz_RevertWhen_UnauthorizedAccept(address) (runs: 256, μ: 40785, ~: 40785) -OwnerTwoStepsFacetTest:testFuzz_RevertWhen_UnauthorizedTransfer(address,address) (runs: 256, μ: 13658, ~: 13658) -OwnerTwoStepsFacetTest:testFuzz_StateAfterRenounce(address,address) (runs: 256, μ: 21807, ~: 21807) -OwnerTwoStepsFacetTest:testFuzz_TransferOwnership(address) (runs: 256, μ: 38815, ~: 38815) -OwnerTwoStepsFacetTest:test_AcceptOwnership_ClearsPendingOwner() (gas: 34084) -OwnerTwoStepsFacetTest:test_AcceptOwnership_CompletesTransfer() (gas: 34963) -OwnerTwoStepsFacetTest:test_AcceptOwnership_EmitsOwnershipTransferredEvent() (gas: 33241) -OwnerTwoStepsFacetTest:test_DirectRenounce_vs_TwoStepRenounce() (gas: 41265) -OwnerTwoStepsFacetTest:test_MultiplePendingChanges_OnlyLastOneMatters() (gas: 46144) -OwnerTwoStepsFacetTest:test_Owner_ReturnsCorrectInitialOwner() (gas: 9904) -OwnerTwoStepsFacetTest:test_PendingOwner_InitiallyZero() (gas: 9936) -OwnerTwoStepsFacetTest:test_RenounceOwnership_CannotBeReversed() (gas: 19956) -OwnerTwoStepsFacetTest:test_RenounceOwnership_ClearsPendingOwner() (gas: 35924) -OwnerTwoStepsFacetTest:test_RenounceOwnership_DirectlyRenounces() (gas: 18894) -OwnerTwoStepsFacetTest:test_RenounceOwnership_EmitsOwnershipTransferredEvent() (gas: 18719) -OwnerTwoStepsFacetTest:test_RenounceOwnership_OnlyOwnerCanCall() (gas: 17677) -OwnerTwoStepsFacetTest:test_RenounceOwnership_PreventsAllFutureTransfers() (gas: 24288) -OwnerTwoStepsFacetTest:test_RenounceOwnership_TwoStep() (gas: 20911) -OwnerTwoStepsFacetTest:test_RenounceOwnership_WithPendingTransfer() (gas: 37293) -OwnerTwoStepsFacetTest:test_RevertWhen_AcceptOwnership_CalledByCurrentOwner() (gas: 40269) -OwnerTwoStepsFacetTest:test_RevertWhen_AcceptOwnership_CalledByNonPendingOwner() (gas: 42247) -OwnerTwoStepsFacetTest:test_RevertWhen_AcceptOwnership_NoPendingOwner() (gas: 12984) -OwnerTwoStepsFacetTest:test_RevertWhen_RenounceOwnership_CalledByNonOwner() (gas: 18077) -OwnerTwoStepsFacetTest:test_RevertWhen_RenounceOwnership_CalledByPendingOwner() (gas: 40234) -OwnerTwoStepsFacetTest:test_RevertWhen_TransferOwnership_CalledByNonOwner() (gas: 13120) -OwnerTwoStepsFacetTest:test_RevertWhen_TransferOwnership_CalledByPendingOwner() (gas: 42405) -OwnerTwoStepsFacetTest:test_SequentialTransfers() (gas: 78479) -OwnerTwoStepsFacetTest:test_StorageSlot_Consistency() (gas: 33047) -OwnerTwoStepsFacetTest:test_StorageSlot_PendingOwner() (gas: 40490) -OwnerTwoStepsFacetTest:test_TransferOwnership_CanCancelBySettingToZero() (gas: 32766) -OwnerTwoStepsFacetTest:test_TransferOwnership_CanTransferToZeroAddress() (gas: 19834) -OwnerTwoStepsFacetTest:test_TransferOwnership_CanUpdatePendingOwner() (gas: 46268) -OwnerTwoStepsFacetTest:test_TransferOwnership_EmitsOwnershipTransferStartedEvent() (gas: 40705) -OwnerTwoStepsFacetTest:test_TransferOwnership_OnlyOwnerCanInitiate() (gas: 40855) -OwnerTwoStepsFacetTest:test_TransferToSelf() (gas: 29526) -RoyaltyFacetTest:testFuzz_RoyaltyInfo_WithTokenRoyalty(uint256,uint96,uint256) (runs: 256, μ: 35372, ~: 35372) -RoyaltyFacetTest:testFuzz_RoyaltyInfo_WithValidFee(uint96,uint256) (runs: 256, μ: 37394, ~: 37394) -RoyaltyFacetTest:test_ComplexScenario_MultipleTokensAndDefaults() (gas: 88091) -RoyaltyFacetTest:test_RoyaltyInfo_100PercentRoyalty() (gas: 33857) -RoyaltyFacetTest:test_RoyaltyInfo_10PercentRoyalty() (gas: 33880) -RoyaltyFacetTest:test_RoyaltyInfo_50PercentRoyalty() (gas: 33880) -RoyaltyFacetTest:test_RoyaltyInfo_5PercentRoyalty() (gas: 33902) -RoyaltyFacetTest:test_RoyaltyInfo_DefaultRoyaltyAddress() (gas: 33873) -RoyaltyFacetTest:test_RoyaltyInfo_DefaultRoyaltyOnly() (gas: 34030) -RoyaltyFacetTest:test_RoyaltyInfo_FallsBackWhenTokenRoyaltyNotSet() (gas: 33882) -RoyaltyFacetTest:test_RoyaltyInfo_FractionalRoyalty() (gas: 33903) -RoyaltyFacetTest:test_RoyaltyInfo_LargeSalePrice() (gas: 34006) -RoyaltyFacetTest:test_RoyaltyInfo_MinimalRoyaltyFee() (gas: 33857) -RoyaltyFacetTest:test_RoyaltyInfo_MultipleTokensDifferentRoyalties() (gas: 88083) -RoyaltyFacetTest:test_RoyaltyInfo_NoRoyaltySet() (gas: 10550) -RoyaltyFacetTest:test_RoyaltyInfo_SmallTokenId() (gas: 31870) -RoyaltyFacetTest:test_RoyaltyInfo_TokenSpecificOverridesDefault() (gas: 57117) -RoyaltyFacetTest:test_RoyaltyInfo_TokenSpecificRoyalty() (gas: 31852) -RoyaltyFacetTest:test_RoyaltyInfo_VariousFeePercentages() (gas: 51525) -RoyaltyFacetTest:test_RoyaltyInfo_VariousTokenIds() (gas: 86089) -RoyaltyFacetTest:test_RoyaltyInfo_VeryLargeTokenId() (gas: 31882) -RoyaltyFacetTest:test_RoyaltyInfo_WithMaximumValues() (gas: 33894) -RoyaltyFacetTest:test_RoyaltyInfo_ZeroAddressReceiverReturnsZero() (gas: 10540) -RoyaltyFacetTest:test_RoyaltyInfo_ZeroRoyaltyPercentage() (gas: 33871) -RoyaltyFacetTest:test_RoyaltyInfo_ZeroSalePrice() (gas: 33891) -RoyaltyFacetTest:test_StorageSlot_Consistency() (gas: 33804) -RoyaltyFacetTest:test_StorageSlot_TokenRoyaltyConsistency() (gas: 31798) \ No newline at end of file