Platform: Code4rena
Start Date: 02/10/2023
Pot Size: $1,100,000 USDC
Total HM: 28
Participants: 64
Period: 21 days
Judge: GalloDaSballo
Total Solo HM: 13
Id: 292
League: ETH
Rank: 61/64
Findings: 1
Award: $95.22
π Selected for report: 0
π Solo Findings: 0
π Selected for report: erebus
Also found by: 0xTheC0der, Bauchibred, HE1M, Jorgect, Udsen, alexfilippov314, chaduke, evmboi32, hash, ladboy233, lsaudit, oakcobalt, rvierdiiev, ustas, wangxx2026, xuwinnie, zero-idea, zkrunner
95.2225 USDC - $95.22
When a facet has not more selectors to delete, the contract delete the facet this is made it in the _removeFacet function deleting address of the facet, but the function is missing delete the position of the facet, this is in a important variable and is used in the important functions of the contract leading to mistakes.
_removeFacet function:
file:code/contracts/ethereum/contracts/zksync/libraries/Diamond.sol function _removeFacet(address _facet) private { DiamondStorage storage ds = getDiamondStorage(); // Get index of `DiamondStorage.facets` of the facet and last element of array uint256 facetPosition = ds.facetToSelectors[_facet].facetPosition; uint256 lastFacetPosition = ds.facets.length - 1; // If the facet is not at the end of the array then move the last element to the facet position if (facetPosition != lastFacetPosition) { address lastFacet = ds.facets[lastFacetPosition]; ds.facets[facetPosition] = lastFacet; ds.facetToSelectors[lastFacet].facetPosition = facetPosition.toUint16(); } // Remove last element from the facets array ds.facets.pop(); @---> ds.facetToSelectors[lastFacet].facetPosition is not deleted }
This can be see it in other implementation of the diamond proxy like diamond-3-hardhat
Manual review
Delete the ds.facetToSelectors[lastFacet].facetPosition in the Diamond.sol
function _removeFacet(address _facet) private { DiamondStorage storage ds = getDiamondStorage(); // Get index of `DiamondStorage.facets` of the facet and last element of array uint256 facetPosition = ds.facetToSelectors[_facet].facetPosition; uint256 lastFacetPosition = ds.facets.length - 1; // If the facet is not at the end of the array then move the last element to the facet position if (facetPosition != lastFacetPosition) { address lastFacet = ds.facets[lastFacetPosition]; ds.facets[facetPosition] = lastFacet; ds.facetToSelectors[lastFacet].facetPosition = facetPosition.toUint16(); } // Remove last element from the facets array ds.facets.pop(); delete ds.facetToSelectors[lastFacet].facetPosition; @-------> deleting the position }
Other
#0 - c4-pre-sort
2023-11-01T14:50:17Z
bytes032 marked the issue as low quality report
#1 - miladpiri
2023-11-08T15:08:11Z
It does not lead to any issue, so QA.
#2 - c4-sponsor
2023-11-08T15:08:15Z
miladpiri marked the issue as disagree with severity
#3 - c4-sponsor
2023-11-08T15:08:31Z
miladpiri (sponsor) acknowledged
#4 - GalloDaSballo
2023-11-26T12:42:15Z
Unfortunately, the warden stopped and did not show how this can cause issues
I agree with downgrading
#5 - c4-judge
2023-11-26T12:42:19Z
GalloDaSballo changed the severity to QA (Quality Assurance)