-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1f2984f
commit fe18ecc
Showing
1 changed file
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
/* | ||
This file is part of the Enzyme Protocol. | ||
(c) Enzyme Council <council@enzyme.finance> | ||
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 <security@enzyme.finance> | ||
/// @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_; | ||
} | ||
} |