Skip to content

Commit

Permalink
introduces LibDiamondLoupe to avoid external calls for loupe functions
Browse files Browse the repository at this point in the history
  • Loading branch information
0xDEnYO committed Jul 23, 2024
1 parent 136b8bb commit 69cf5f4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 9 deletions.
16 changes: 7 additions & 9 deletions src/Facets/EmergencyPauseFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity 0.8.17;

import { LibDiamond } from "../Libraries/LibDiamond.sol";
import { LibDiamondLoupe } from "../Libraries/LibDiamondLoupe.sol";
import { UnAuthorized, InvalidCallData, DiamondIsPaused } from "../Errors/GenericErrors.sol";
import { IDiamondCut } from "lifi/Interfaces/IDiamondCut.sol";
import { IDiamondLoupe } from "lifi/Interfaces/IDiamondLoupe.sol";
Expand Down Expand Up @@ -57,8 +58,10 @@ contract EmergencyPauseFacet {
address _facetAddress
) external OnlyPauserWalletOrOwner(msg.sender) {
// get function selectors for this facet
bytes4[] memory functionSelectors = DiamondLoupeFacet(address(this))
.facetFunctionSelectors(_facetAddress);
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
bytes4[] memory functionSelectors = ds
.facetFunctionSelectors[_facetAddress]
.functionSelectors;

// do not continue if no registered function selectors were found
if (functionSelectors.length == 0) revert FacetIsNotRegistered();
Expand Down Expand Up @@ -132,14 +135,11 @@ contract EmergencyPauseFacet {
// It would be easier to not reinstate these facets in the first place but
// a) that would leave their function selectors associated with address of EmergencyPauseFacet (=> throws 'DiamondIsPaused() error when called)
// b) it consumes a lot of gas to check every facet address if it's part of the blacklist
// go through all blacklisted facets
for (uint256 i; i < _blacklist.length; ) {
// re-add facet and its selectors to diamond
LibDiamond.removeFunctions(
address(0),
DiamondLoupeFacet(address(this)).facetFunctionSelectors(
_blacklist[i]
)
LibDiamondLoupe.facetFunctionSelectors(_blacklist[i])
);

// gas-efficient way to increase loop counter
Expand Down Expand Up @@ -187,9 +187,7 @@ contract EmergencyPauseFacet {
returns (IDiamondLoupe.Facet[] memory toBeRemoved)
{
// get a list of all registered facet addresses
IDiamondLoupe.Facet[] memory allFacets = DiamondLoupeFacet(
address(this)
).facets();
IDiamondLoupe.Facet[] memory allFacets = LibDiamondLoupe.facets();

// initiate return variable with allFacets length - 1 (since we will not remove the EmergencyPauseFacet)
delete toBeRemoved;
Expand Down
55 changes: 55 additions & 0 deletions src/Libraries/LibDiamondLoupe.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import { LibDiamond } from "../Libraries/LibDiamond.sol";
import { IDiamondLoupe } from "../Interfaces/IDiamondLoupe.sol";

/// Library for DiamondLoupe functions (to avoid using external calls when using DiamondLoupe)
library LibDiamondLoupe {
function facets()
internal
view
returns (IDiamondLoupe.Facet[] memory facets_)
{
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
uint256 numFacets = ds.facetAddresses.length;
facets_ = new IDiamondLoupe.Facet[](numFacets);
for (uint256 i = 0; i < numFacets; ) {
address facetAddress_ = ds.facetAddresses[i];
facets_[i].facetAddress = facetAddress_;
facets_[i].functionSelectors = ds
.facetFunctionSelectors[facetAddress_]
.functionSelectors;
unchecked {
++i;
}
}
}

function facetFunctionSelectors(
address _facet
) internal view returns (bytes4[] memory facetFunctionSelectors_) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetFunctionSelectors_ = ds
.facetFunctionSelectors[_facet]
.functionSelectors;
}

function facetAddresses()
internal
view
returns (address[] memory facetAddresses_)
{
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetAddresses_ = ds.facetAddresses;
}

function facetAddress(
bytes4 _functionSelector
) internal view returns (address facetAddress_) {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
facetAddress_ = ds
.selectorToFacetAndPosition[_functionSelector]
.facetAddress;
}
}

0 comments on commit 69cf5f4

Please sign in to comment.