From cfb220fe79db75f7254228926ca963a53dcfd629 Mon Sep 17 00:00:00 2001 From: atarpara Date: Sat, 29 Aug 2026 14:26:01 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20Fix=20EnumerableSetLib.indexOf?= =?UTF-8?q?=20for=20AddressSet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/EnumerableSetLib.sol | 1 + src/utils/g/EnumerableSetLib.sol | 1 + test/EnumerableSetLib.t.sol | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/src/utils/EnumerableSetLib.sol b/src/utils/EnumerableSetLib.sol index 723edb4e28..79729d9e3f 100644 --- a/src/utils/EnumerableSetLib.sol +++ b/src/utils/EnumerableSetLib.sol @@ -772,6 +772,7 @@ library EnumerableSetLib { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { + value := shr(96, shl(96, value)) if iszero(value) { value := _ZERO_SENTINEL } result := not(0) let rootPacked := sload(rootSlot) diff --git a/src/utils/g/EnumerableSetLib.sol b/src/utils/g/EnumerableSetLib.sol index 2a240a9ab5..bee5f85ee1 100644 --- a/src/utils/g/EnumerableSetLib.sol +++ b/src/utils/g/EnumerableSetLib.sol @@ -780,6 +780,7 @@ library EnumerableSetLib { bytes32 rootSlot = _rootSlot(set); /// @solidity memory-safe-assembly assembly { + value := shr(96, shl(96, value)) if iszero(value) { value := _ZERO_SENTINEL } result := not(0) let rootPacked := sload(rootSlot) diff --git a/test/EnumerableSetLib.t.sol b/test/EnumerableSetLib.t.sol index a8964ba619..aa767cf79b 100644 --- a/test/EnumerableSetLib.t.sol +++ b/test/EnumerableSetLib.t.sol @@ -904,4 +904,36 @@ contract EnumerableSetLibTest is SoladyTest { } } } + + function testIndexOfDirtyUpperBits() public { + addressSet.add(address(0)); + for (uint256 i = 1; i != 5; ++i) { + addressSet.add(address(uint160(i))); + } + assertEq(addressSet.length(), 5); + + address dirtyZero = _dirtyAddress(address(0), 1); + assertTrue(addressSet.contains(dirtyZero)); + assertEq(addressSet.indexOf(dirtyZero), 0); + + address dirtyThree = _dirtyAddress(address(uint160(3)), 0xabc); + assertTrue(addressSet.contains(dirtyThree)); + assertEq(addressSet.indexOf(dirtyThree), addressSet.indexOf(address(uint160(3)))); + } + + function testIndexOfDirtyUpperBitsLazy() public { + addressSet.add(address(0)); + addressSet.add(address(uint160(1))); + assertEq(addressSet.length(), 2); + + assertEq(addressSet.indexOf(_dirtyAddress(address(0), 1)), 0); + assertEq(addressSet.indexOf(_dirtyAddress(address(uint160(1)), 0xabc)), 1); + } + + function _dirtyAddress(address a, uint256 dirt) internal pure returns (address result) { + /// @solidity memory-safe-assembly + assembly { + result := or(a, shl(160, dirt)) + } + } }