From fe18ecc2a7dd6d40a7da037e13f457de63ec1ca0 Mon Sep 17 00:00:00 2001 From: Sean Casey Date: Tue, 26 Mar 2024 12:27:32 -0400 Subject: [PATCH] refactor: add int256 array lib --- contracts/utils/0.8.19/Int256ArrayLib.sol | 176 ++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 contracts/utils/0.8.19/Int256ArrayLib.sol diff --git a/contracts/utils/0.8.19/Int256ArrayLib.sol b/contracts/utils/0.8.19/Int256ArrayLib.sol new file mode 100644 index 000000000..56d8a1101 --- /dev/null +++ b/contracts/utils/0.8.19/Int256ArrayLib.sol @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-3.0 + +/* + This file is part of the Enzyme Protocol. + + (c) Enzyme Council + + For the full license information, please view the LICENSE + file that was distributed with this source code. +*/ + +pragma solidity 0.8.19; + +/// @title Int256Array Library +/// @author Enzyme Council +/// @notice A library to extend the int256 array data type +library Int256ArrayLib { + ///////////// + // STORAGE // + ///////////// + + /// @dev Helper to remove an item from a storage array + function removeStorageItem(int256[] storage _self, int256 _itemToRemove) internal returns (bool removed_) { + uint256 itemCount = _self.length; + for (uint256 i; i < itemCount; i++) { + if (_self[i] == _itemToRemove) { + if (i < itemCount - 1) { + _self[i] = _self[itemCount - 1]; + } + _self.pop(); + removed_ = true; + break; + } + } + + return removed_; + } + + /// @dev Helper to verify if a storage array contains a particular value + function storageArrayContains(int256[] storage _self, int256 _target) internal view returns (bool doesContain_) { + uint256 arrLength = _self.length; + for (uint256 i; i < arrLength; i++) { + if (_target == _self[i]) { + return true; + } + } + return false; + } + + //////////// + // MEMORY // + //////////// + + /// @dev Helper to add an item to an array. Does not assert uniqueness of the new item. + function addItem(int256[] memory _self, int256 _itemToAdd) internal pure returns (int256[] memory nextArray_) { + nextArray_ = new int256[](_self.length + 1); + for (uint256 i; i < _self.length; i++) { + nextArray_[i] = _self[i]; + } + nextArray_[_self.length] = _itemToAdd; + + return nextArray_; + } + + /// @dev Helper to add an item to an array, only if it is not already in the array. + function addUniqueItem(int256[] memory _self, int256 _itemToAdd) + internal + pure + returns (int256[] memory nextArray_) + { + if (contains(_self, _itemToAdd)) { + return _self; + } + + return addItem(_self, _itemToAdd); + } + + /// @dev Helper to verify if an array contains a particular value + function contains(int256[] memory _self, int256 _target) internal pure returns (bool doesContain_) { + for (uint256 i; i < _self.length; i++) { + if (_target == _self[i]) { + return true; + } + } + return false; + } + + /// @dev Helper to merge the unique items of a second array. + /// Does not consider uniqueness of either array, only relative uniqueness. + /// Preserves ordering. + function mergeArray(int256[] memory _self, int256[] memory _arrayToMerge) + internal + pure + returns (int256[] memory nextArray_) + { + uint256 newUniqueItemCount; + for (uint256 i; i < _arrayToMerge.length; i++) { + if (!contains(_self, _arrayToMerge[i])) { + newUniqueItemCount++; + } + } + + if (newUniqueItemCount == 0) { + return _self; + } + + nextArray_ = new int256[](_self.length + newUniqueItemCount); + for (uint256 i; i < _self.length; i++) { + nextArray_[i] = _self[i]; + } + uint256 nextArrayIndex = _self.length; + for (uint256 i; i < _arrayToMerge.length; i++) { + if (!contains(_self, _arrayToMerge[i])) { + nextArray_[nextArrayIndex] = _arrayToMerge[i]; + nextArrayIndex++; + } + } + + return nextArray_; + } + + /// @dev Helper to verify if array is a set of unique values. + /// Does not assert length > 0. + function isUniqueSet(int256[] memory _self) internal pure returns (bool isUnique_) { + if (_self.length <= 1) { + return true; + } + + uint256 arrayLength = _self.length; + for (uint256 i; i < arrayLength; i++) { + for (uint256 j = i + 1; j < arrayLength; j++) { + if (_self[i] == _self[j]) { + return false; + } + } + } + + return true; + } + + /// @dev Helper to remove items from an array. Removes all matching occurrences of each item. + /// Does not assert uniqueness of either array. + function removeItems(int256[] memory _self, int256[] memory _itemsToRemove) + internal + pure + returns (int256[] memory nextArray_) + { + if (_itemsToRemove.length == 0) { + return _self; + } + + bool[] memory indexesToRemove = new bool[](_self.length); + uint256 remainingItemsCount = _self.length; + for (uint256 i; i < _self.length; i++) { + if (contains(_itemsToRemove, _self[i])) { + indexesToRemove[i] = true; + remainingItemsCount--; + } + } + + if (remainingItemsCount == _self.length) { + nextArray_ = _self; + } else if (remainingItemsCount > 0) { + nextArray_ = new int256[](remainingItemsCount); + uint256 nextArrayIndex; + for (uint256 i; i < _self.length; i++) { + if (!indexesToRemove[i]) { + nextArray_[nextArrayIndex] = _self[i]; + nextArrayIndex++; + } + } + } + + return nextArray_; + } +}