LibInternal Code Style Findings

LibInternal Code Style Findings

LIL-01C: Inefficient Function Signature Computation

Type Severity Location
Gas Optimization LibInternal.sol:L53, L62, L71

Description:

The linked code computes the function selectors it requires on each function invocation redundantly.

Example:

protocol/contracts/libraries/LibInternal.sol
51function updateSilo(address account) internal {
52 DiamondStorage storage ds = diamondStorage();
53 bytes4 functionSelector = bytes4(keccak256("updateSilo(address)"));
54 address facet = ds.selectorToFacetAndPosition[functionSelector].facetAddress;
55 bytes memory myFunctionCall = abi.encodeWithSelector(functionSelector, account);
56 (bool success,) = address(facet).delegatecall(myFunctionCall);
57 require(success, "Silo: updateSilo failed.");
58}
59
60function updateBip(uint32 bip) internal {
61 DiamondStorage storage ds = diamondStorage();
62 bytes4 functionSelector = bytes4(keccak256("updateBip(uint32)"));
63 address facet = ds.selectorToFacetAndPosition[functionSelector].facetAddress;
64 bytes memory myFunctionCall = abi.encodeWithSelector(functionSelector, bip);
65 (bool success,) = address(facet).delegatecall(myFunctionCall);
66 require(success, "Silo: updateBip failed.");
67}
68
69function stalkFor(uint32 bip) internal returns (uint256 stalk) {
70 DiamondStorage storage ds = diamondStorage();
71 bytes4 functionSelector = bytes4(keccak256("stalkFor(uint32)"));
72 address facet = ds.selectorToFacetAndPosition[functionSelector].facetAddress;
73 bytes memory myFunctionCall = abi.encodeWithSelector(functionSelector, bip);
74 (bool success, bytes memory data) = address(facet).delegatecall(myFunctionCall);
75 require(success, "Governance: stalkFor failed.");
76 assembly { stalk := mload(add(data, add(0x20, 0))) }
77}

Recommendation:

We advise the pre-calculated function selectors to be utilised instead by using the standardised ContractInterface.functionName.selector code representation and importing the relevant interfaces.

Alleviation:

The function selector is now properly accessed via the selector member exposed by the function within the interface.

View Fix on GitHub
Navigated to LibInternal Code Style Findings