diff --git a/contracts/data/BinaryHeap.sol b/contracts/data/BinaryHeap.sol deleted file mode 100644 index 133c1a5bb..000000000 --- a/contracts/data/BinaryHeap.sol +++ /dev/null @@ -1,300 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.20; - -/** - * @title Binary Heap implementation - * @dev The data structure is configured as a max-heap - */ -library BinaryHeap { - struct Heap { - bytes32[] _values; - // 1-indexed to allow 0 to signify nonexistence - mapping(bytes32 => uint256) _indexes; - } - - struct Bytes32Heap { - Heap _inner; - } - - struct AddressHeap { - Heap _inner; - } - - struct UintHeap { - Heap _inner; - } - - function at( - Bytes32Heap storage heap, - uint256 index - ) internal view returns (bytes32) { - return _at(heap._inner, index); - } - - function at( - AddressHeap storage heap, - uint256 index - ) internal view returns (address) { - return address(uint160(uint256(_at(heap._inner, index)))); - } - - function at( - UintHeap storage heap, - uint256 index - ) internal view returns (uint256) { - return uint256(_at(heap._inner, index)); - } - - function contains( - Bytes32Heap storage heap, - bytes32 value - ) internal view returns (bool) { - return _contains(heap._inner, value); - } - - function contains( - AddressHeap storage heap, - address value - ) internal view returns (bool) { - return _contains(heap._inner, bytes32(uint256(uint160(value)))); - } - - function contains( - UintHeap storage heap, - uint256 value - ) internal view returns (bool) { - return _contains(heap._inner, bytes32(value)); - } - - function indexOf( - Bytes32Heap storage heap, - bytes32 value - ) internal view returns (uint256) { - return _indexOf(heap._inner, value); - } - - function indexOf( - AddressHeap storage heap, - address value - ) internal view returns (uint256) { - return _indexOf(heap._inner, bytes32(uint256(uint160(value)))); - } - - function indexOf( - UintHeap storage heap, - uint256 value - ) internal view returns (uint256) { - return _indexOf(heap._inner, bytes32(value)); - } - - function length(Bytes32Heap storage heap) internal view returns (uint256) { - return _length(heap._inner); - } - - function length(AddressHeap storage heap) internal view returns (uint256) { - return _length(heap._inner); - } - - function length(UintHeap storage heap) internal view returns (uint256) { - return _length(heap._inner); - } - - function root(Bytes32Heap storage heap) internal view returns (bytes32) { - return _root(heap._inner); - } - - function root(AddressHeap storage heap) internal view returns (address) { - return address(uint160(uint256(_root(heap._inner)))); - } - - function root(UintHeap storage heap) internal view returns (uint256) { - return uint256(_root(heap._inner)); - } - - function add( - Bytes32Heap storage heap, - bytes32 value - ) internal returns (bool) { - return _add(heap._inner, value); - } - - function add( - AddressHeap storage heap, - address value - ) internal returns (bool) { - return _add(heap._inner, bytes32(uint256(uint160(value)))); - } - - function add(UintHeap storage heap, uint256 value) internal returns (bool) { - return _add(heap._inner, bytes32(value)); - } - - function remove( - Bytes32Heap storage heap, - bytes32 value - ) internal returns (bool) { - return _remove(heap._inner, value); - } - - function remove( - AddressHeap storage heap, - address value - ) internal returns (bool) { - return _remove(heap._inner, bytes32(uint256(uint160(value)))); - } - - function remove( - UintHeap storage heap, - uint256 value - ) internal returns (bool) { - return _remove(heap._inner, bytes32(value)); - } - - function toArray( - Bytes32Heap storage heap - ) internal view returns (bytes32[] memory) { - return heap._inner._values; - } - - function toArray( - AddressHeap storage heap - ) internal view returns (address[] memory) { - bytes32[] storage values = heap._inner._values; - address[] storage array; - - assembly { - array.slot := values.slot - } - - return array; - } - - function toArray( - UintHeap storage heap - ) internal view returns (uint256[] memory) { - bytes32[] storage values = heap._inner._values; - uint256[] storage array; - - assembly { - array.slot := values.slot - } - - return array; - } - - function _at( - Heap storage heap, - uint256 index - ) private view returns (bytes32) { - return heap._values[index]; - } - - function _contains( - Heap storage heap, - bytes32 value - ) private view returns (bool) { - return heap._indexes[value] != 0; - } - - function _indexOf( - Heap storage heap, - bytes32 value - ) private view returns (uint256) { - unchecked { - return heap._indexes[value] - 1; - } - } - - function _length(Heap storage heap) private view returns (uint256) { - return heap._values.length; - } - - function _root(Heap storage heap) private view returns (bytes32) { - return _at(heap, 0); - } - - function _add( - Heap storage heap, - bytes32 value - ) private returns (bool update) { - if (!_contains(heap, value)) { - heap._values.push(value); - heap._indexes[value] = _length(heap); - _heapify(heap); - - update = true; - } - } - - function _remove( - Heap storage heap, - bytes32 value - ) private returns (bool update) { - if (_contains(heap, value)) { - uint256 index = _indexOf(heap, value); - - unchecked { - // move node with last element in the tree, then remove it - _swap(heap, index, _length(heap) - 1); - } - - heap._values.pop(); - delete heap._indexes[value]; - - _heapify(heap); - - update = true; - } - } - - function _heapify(Heap storage heap) private { - uint256 len = _length(heap); - unchecked { - uint256 index = len / 2; - while (index > 0) { - _maxHeapify(heap, len, --index); - } - } - } - - function _maxHeapify( - Heap storage heap, - uint256 len, - uint256 index - ) private { - uint256 largest = index; - bytes32[] storage values = heap._values; - - unchecked { - uint256 left = (index << 1) | 1; - uint256 right = left + 1; - - if (left < len && values[largest] < values[left]) { - largest = left; - } - - if (right < len && values[largest] < values[right]) { - largest = right; - } - } - - if (largest != index) { - // swap until the largest node is the root node - _swap(heap, index, largest); - _maxHeapify(heap, len, largest); - } - } - - function _swap(Heap storage heap, uint256 a, uint256 b) private { - bytes32[] storage values = heap._values; - - bytes32 aValue = values[a]; - bytes32 bValue = values[b]; - - (values[a], values[b]) = (bValue, aValue); - - mapping(bytes32 => uint256) storage indexes = heap._indexes; - (indexes[aValue], indexes[bValue]) = (indexes[bValue], indexes[aValue]); - } -} diff --git a/test/data/BinaryHeap.ts b/test/data/BinaryHeap.ts deleted file mode 100644 index 9ba6f64d6..000000000 --- a/test/data/BinaryHeap.ts +++ /dev/null @@ -1,931 +0,0 @@ -import { PANIC_CODES } from '@nomicfoundation/hardhat-chai-matchers/panic'; -import { bigintToBytes32, bigintToAddress } from '@solidstate/library'; -import { $BinaryHeap, $BinaryHeap__factory } from '@solidstate/typechain-types'; -import { expect } from 'chai'; -import { ethers } from 'hardhat'; - -// data structures can be defined at any storage slot -// it doesn't matter which slot is used as long as it's consistent -const STORAGE_SLOT = 0n; - -const numbers = [0, 1, 2].map((n) => n); - -const constants = { - bytes32: numbers.map((n) => bigintToBytes32(n)), - address: numbers.map((n) => bigintToAddress(n)), - uint256: numbers, -}; - -const randomBytes32 = () => ethers.hexlify(ethers.randomBytes(32)); - -const randomAddress = () => - ethers.getAddress(ethers.zeroPadValue(ethers.randomBytes(20), 20)); - -const randomUint256 = () => BigInt(ethers.toQuantity(ethers.randomBytes(32))); - -// checks that the parent node is greater than or equal to the children nodes -function checkNodes(nodes: any[]) { - nodes.forEach((node, index) => { - const left = 2 * index + 1; - const right = 2 * index + 2; - - if (left < nodes.length && nodes[left] != null) { - expect(BigInt(node)).to.be.gte(BigInt(nodes[left])); - } - - if (right < nodes.length && nodes[right] != null) { - expect(BigInt(node)).to.be.gte(BigInt(nodes[right])); - } - }); -} - -describe('BinaryHeap', async () => { - describe('Bytes32Heap', async () => { - let instance: $BinaryHeap; - - beforeEach(async () => { - const [deployer] = await ethers.getSigners(); - instance = await new $BinaryHeap__factory(deployer).deploy(); - }); - - describe('__internal', () => { - describe('#at(bytes32)', () => { - it('returns the value corresponding to index provided', async () => { - await instance['$add(uint256,bytes32)']( - STORAGE_SLOT, - randomBytes32(), - ); - await instance['$add(uint256,bytes32)']( - STORAGE_SLOT, - randomBytes32(), - ); - await instance['$add(uint256,bytes32)']( - STORAGE_SLOT, - randomBytes32(), - ); - - const array = - await instance.$toArray_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ); - - for (const key in array) { - const value = await instance.$at_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - key, - ); - expect(value).to.equal(array[key]); - } - }); - - describe('reverts if', () => { - it('index out of bounds', async () => { - await expect( - instance.$at_BinaryHeap_Bytes32Heap(STORAGE_SLOT, 0n), - ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS); - }); - }); - }); - - describe('#contains(bytes32)', () => { - it('returns true if the value has been added', async () => { - const value = randomBytes32(); - - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, value); - - expect( - await instance['$contains(uint256,bytes32)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.true; - }); - - it('returns false if the value has not been added', async () => { - expect( - await instance['$contains(uint256,bytes32)']( - STORAGE_SLOT, - randomBytes32(), - ), - ).to.be.false; - }); - }); - - describe('#indexOf(bytes32)', () => { - it('returns index of the value', async () => { - await instance['$add(uint256,bytes32)']( - STORAGE_SLOT, - randomBytes32(), - ); - await instance['$add(uint256,bytes32)']( - STORAGE_SLOT, - randomBytes32(), - ); - await instance['$add(uint256,bytes32)']( - STORAGE_SLOT, - randomBytes32(), - ); - - const array = - await instance.$toArray_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ); - - for (const key in array) { - const value = array[key]; - const index = await instance[ - '$indexOf(uint256,bytes32)' - ].staticCall(STORAGE_SLOT, value); - expect(index).to.equal(key); - } - }); - - it('returns max uint256 if value does not exist', async () => { - expect( - await instance['$indexOf(uint256,bytes32)'].staticCall( - STORAGE_SLOT, - randomBytes32(), - ), - ).to.equal(ethers.MaxUint256); - }); - }); - - describe('#length()', () => { - it('returns length of binary heap', async () => { - const values = [randomBytes32(), randomBytes32(), randomBytes32()]; - - expect( - await instance.$length_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(0); - - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, values[0]); - expect( - await instance.$length_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(1); - - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, values[1]); - expect( - await instance.$length_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(2); - - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, values[2]); - expect( - await instance.$length_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(3); - - await instance['$remove(uint256,bytes32)'](STORAGE_SLOT, values[0]); - expect( - await instance.$length_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(2); - - await instance['$remove(uint256,bytes32)'](STORAGE_SLOT, values[1]); - expect( - await instance.$length_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(1); - - await instance['$remove(uint256,bytes32)'](STORAGE_SLOT, values[2]); - expect( - await instance.$length_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(0); - }); - }); - - describe('#root()', () => { - it('returns the highest value in the heap', async () => { - const [min, mid, max] = constants.bytes32; - - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, min); - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, mid); - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, max); - - expect( - await instance.$root_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(max); - - await instance['$remove(uint256,bytes32)'](STORAGE_SLOT, max); - - expect( - await instance.$root_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(mid); - - await instance['$remove(uint256,bytes32)'](STORAGE_SLOT, mid); - - expect( - await instance.$root_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(min); - }); - - describe('reverts if', () => { - it('index out of bounds', async () => { - await expect( - instance.$root_BinaryHeap_Bytes32Heap.staticCall(STORAGE_SLOT), - ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS); - }); - }); - }); - - describe('#add(bytes32)', () => { - it('sets the parent node such that it is greater than or equal to the values of its children when a node is added', async () => { - for (let index = 0; index < 10; index++) { - const value = randomBytes32(); - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, value); - const nodes = - await instance.$toArray_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ); - checkNodes(Array.from(nodes)); - } - }); - - it('returns true if value is added', async () => { - expect( - await instance['$add(uint256,bytes32)'].staticCall( - STORAGE_SLOT, - randomBytes32(), - ), - ).to.be.true; - }); - - it('returns false if value has already been added', async () => { - const value = randomBytes32(); - - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, value); - - expect( - await instance['$add(uint256,bytes32)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.false; - }); - }); - - describe('#remove(bytes32)', () => { - it('sets the parent node such that it is greater than or equal to the values of its children when a node is removed', async () => { - const values: string[] = []; - - for (let index = 0; index < 10; index++) { - const value = randomBytes32(); - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, value); - values.push(value); - } - - for (const value of values) { - await instance['$remove(uint256,bytes32)'](STORAGE_SLOT, value); - checkNodes( - await instance.$toArray_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ), - ); - } - }); - - it('returns true if value is removed', async () => { - const value = randomBytes32(); - - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, value); - - expect( - await instance['$remove(uint256,bytes32)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.true; - }); - - it('returns false if value does not exist', async () => { - expect( - await instance['$remove(uint256,bytes32)'].staticCall( - STORAGE_SLOT, - randomBytes32(), - ), - ).to.be.false; - }); - }); - - describe('#toArray()', () => { - it('returns the max heap as an array', async () => { - const [min, mid, max] = constants.bytes32; - - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, min); - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, mid); - await instance['$add(uint256,bytes32)'](STORAGE_SLOT, max); - - const array = - await instance.$toArray_BinaryHeap_Bytes32Heap.staticCall( - STORAGE_SLOT, - ); - - expect(array.length).to.equal(3); - expect(array).to.deep.equal([max, min, mid]); - }); - }); - }); - }); - - describe('AddressHeap', async () => { - let instance: $BinaryHeap; - - beforeEach(async () => { - const [deployer] = await ethers.getSigners(); - instance = await new $BinaryHeap__factory(deployer).deploy(); - }); - - describe('__internal', () => { - describe('#at(address)', () => { - it('returns the value corresponding to index provided', async () => { - await instance['$add(uint256,address)']( - STORAGE_SLOT, - randomAddress(), - ); - await instance['$add(uint256,address)']( - STORAGE_SLOT, - randomAddress(), - ); - await instance['$add(uint256,address)']( - STORAGE_SLOT, - randomAddress(), - ); - - const array = - await instance.$toArray_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ); - - for (const key in array) { - const value = await instance.$at_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - key, - ); - expect(value).to.equal(array[key]); - } - }); - - describe('reverts if', () => { - it('index out of bounds', async () => { - await expect( - instance.$at_BinaryHeap_AddressHeap.staticCall(STORAGE_SLOT, 0n), - ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS); - }); - }); - }); - - describe('#contains(address)', () => { - it('returns true if the value has been added', async () => { - const value = randomAddress(); - - await instance['$add(uint256,address)'](STORAGE_SLOT, value); - - expect( - await instance['$contains(uint256,address)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.true; - }); - - it('returns false if the value has not been added', async () => { - expect( - await instance['$contains(uint256,address)'].staticCall( - STORAGE_SLOT, - randomAddress(), - ), - ).to.be.false; - }); - }); - - describe('#indexOf(address)', () => { - it('returns index of the value', async () => { - await instance['$add(uint256,address)']( - STORAGE_SLOT, - randomAddress(), - ); - await instance['$add(uint256,address)']( - STORAGE_SLOT, - randomAddress(), - ); - await instance['$add(uint256,address)']( - STORAGE_SLOT, - randomAddress(), - ); - - const array = - await instance.$toArray_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ); - - for (const key in array) { - const value = array[key]; - const index = await instance[ - '$indexOf(uint256,address)' - ].staticCall(STORAGE_SLOT, value); - expect(index).to.equal(key); - } - }); - - it('returns max uint256 if value does not exist', async () => { - expect( - await instance['$indexOf(uint256,address)']( - STORAGE_SLOT, - randomAddress(), - ), - ).to.equal(ethers.MaxUint256); - }); - }); - - describe('#length()', () => { - it('returns length of binary heap', async () => { - const values = [randomAddress(), randomAddress(), randomAddress()]; - - expect( - await instance.$length_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(0); - - await instance['$add(uint256,address)'](STORAGE_SLOT, values[0]); - expect( - await instance.$length_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(1); - - await instance['$add(uint256,address)'](STORAGE_SLOT, values[1]); - expect( - await instance.$length_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(2); - - await instance['$add(uint256,address)'](STORAGE_SLOT, values[2]); - expect( - await instance.$length_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(3); - - await instance['$remove(uint256,address)'](STORAGE_SLOT, values[0]); - expect( - await instance.$length_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(2); - - await instance['$remove(uint256,address)'](STORAGE_SLOT, values[1]); - expect( - await instance.$length_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(1); - - await instance['$remove(uint256,address)'](STORAGE_SLOT, values[2]); - expect( - await instance.$length_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(0); - }); - }); - - describe('#root()', () => { - it('returns the highest value in the heap', async () => { - const [min, mid, max] = constants.address; - - await instance['$add(uint256,address)'](STORAGE_SLOT, min); - await instance['$add(uint256,address)'](STORAGE_SLOT, mid); - await instance['$add(uint256,address)'](STORAGE_SLOT, max); - - expect( - await instance.$root_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(max); - - await instance['$remove(uint256,address)'](STORAGE_SLOT, max); - - expect( - await instance.$root_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(mid); - - await instance['$remove(uint256,address)'](STORAGE_SLOT, mid); - - expect( - await instance.$root_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ).to.equal(min); - }); - - describe('reverts if', () => { - it('index out of bounds', async () => { - await expect( - instance.$root_BinaryHeap_AddressHeap.staticCall(STORAGE_SLOT), - ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS); - }); - }); - }); - - describe('#add(address)', () => { - it('sets the parent node such that it is greater than or equal to the values of its children when a node is added', async () => { - for (let index = 0; index < 10; index++) { - const value = randomAddress(); - await instance['$add(uint256,address)'](STORAGE_SLOT, value); - const nodes = - await instance.$toArray_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ); - checkNodes(Array.from(nodes)); - } - }); - - it('returns true if value is added', async () => { - expect( - await instance['$add(uint256,address)'].staticCall( - STORAGE_SLOT, - randomAddress(), - ), - ).to.be.true; - }); - - it('returns false if value has already been added', async () => { - const value = randomAddress(); - - await instance['$add(uint256,address)'](STORAGE_SLOT, value); - - expect( - await instance['$add(uint256,address)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.false; - }); - }); - - describe('#remove(address)', () => { - it('sets the parent node such that it is greater than or equal to the values of its children when a node is removed', async () => { - const values: string[] = []; - - for (let index = 0; index < 10; index++) { - const value = randomAddress(); - await instance['$add(uint256,address)'](STORAGE_SLOT, value); - values.push(value); - } - - for (const value of values) { - await instance['$remove(uint256,address)'](STORAGE_SLOT, value); - checkNodes( - await instance.$toArray_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ), - ); - } - }); - - it('returns true if value is removed', async () => { - const value = randomAddress(); - - await instance['$add(uint256,address)'](STORAGE_SLOT, value); - - expect( - await instance['$remove(uint256,address)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.true; - }); - - it('returns false if value does not exist', async () => { - expect( - await instance['$remove(uint256,address)'].staticCall( - STORAGE_SLOT, - randomAddress(), - ), - ).to.be.false; - }); - }); - - describe('#toArray()', () => { - it('returns the max heap as an array', async () => { - const [min, mid, max] = constants.address; - - await instance['$add(uint256,address)'](STORAGE_SLOT, min); - await instance['$add(uint256,address)'](STORAGE_SLOT, mid); - await instance['$add(uint256,address)'](STORAGE_SLOT, max); - - const array = - await instance.$toArray_BinaryHeap_AddressHeap.staticCall( - STORAGE_SLOT, - ); - - expect(array.length).to.equal(3); - expect(array).to.deep.equal([max, min, mid]); - }); - }); - }); - }); - - describe('UintHeap', async () => { - let instance: $BinaryHeap; - - beforeEach(async () => { - const [deployer] = await ethers.getSigners(); - instance = await new $BinaryHeap__factory(deployer).deploy(); - }); - - describe('__internal', () => { - describe('#at(uint256)', () => { - it('returns the value corresponding to index provided', async () => { - await instance['$add(uint256,uint256)']( - STORAGE_SLOT, - randomUint256(), - ); - await instance['$add(uint256,uint256)']( - STORAGE_SLOT, - randomUint256(), - ); - await instance['$add(uint256,uint256)']( - STORAGE_SLOT, - randomUint256(), - ); - - const array = - await instance.$toArray_BinaryHeap_UintHeap.staticCall( - STORAGE_SLOT, - ); - - for (const key in array) { - const value = await instance.$at_BinaryHeap_UintHeap.staticCall( - STORAGE_SLOT, - key, - ); - expect(value).to.equal(array[key]); - } - }); - - describe('reverts if', () => { - it('index out of bounds', async () => { - await expect( - instance.$at_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT, 0n), - ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS); - }); - }); - }); - - describe('#contains(uint256)', () => { - it('returns true if the value has been added', async () => { - const value = randomUint256(); - - await instance['$add(uint256,uint256)'](STORAGE_SLOT, value); - - expect( - await instance['$contains(uint256,uint256)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.true; - }); - - it('returns false if the value has not been added', async () => { - expect( - await instance['$contains(uint256,uint256)'].staticCall( - STORAGE_SLOT, - randomUint256(), - ), - ).to.be.false; - }); - }); - - describe('#indexOf(uint256)', () => { - it('returns index of the value', async () => { - await instance['$add(uint256,uint256)']( - STORAGE_SLOT, - randomUint256(), - ); - await instance['$add(uint256,uint256)']( - STORAGE_SLOT, - randomUint256(), - ); - await instance['$add(uint256,uint256)']( - STORAGE_SLOT, - randomUint256(), - ); - - const array = - await instance.$toArray_BinaryHeap_UintHeap.staticCall( - STORAGE_SLOT, - ); - - for (const key in array) { - const value = array[key]; - const index = await instance[ - '$indexOf(uint256,uint256)' - ].staticCall(STORAGE_SLOT, value); - expect(index).to.equal(key); - } - }); - - it('returns max uint256 if value does not exist', async () => { - expect( - await instance['$indexOf(uint256,uint256)'].staticCall( - STORAGE_SLOT, - randomUint256(), - ), - ).to.equal(ethers.MaxUint256); - }); - }); - - describe('#length()', () => { - it('returns length of binary heap', async () => { - const values = [randomUint256(), randomUint256(), randomUint256()]; - - expect( - await instance.$length_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(0); - - await instance['$add(uint256,uint256)'](STORAGE_SLOT, values[0]); - expect( - await instance.$length_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(1); - - await instance['$add(uint256,uint256)'](STORAGE_SLOT, values[1]); - expect( - await instance.$length_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(2); - - await instance['$add(uint256,uint256)'](STORAGE_SLOT, values[2]); - expect( - await instance.$length_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(3); - - await instance['$remove(uint256,uint256)'](STORAGE_SLOT, values[0]); - expect( - await instance.$length_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(2); - - await instance['$remove(uint256,uint256)'](STORAGE_SLOT, values[1]); - expect( - await instance.$length_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(1); - - await instance['$remove(uint256,uint256)'](STORAGE_SLOT, values[2]); - expect( - await instance.$length_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(0); - }); - }); - - describe('#root()', () => { - it('returns the highest value in the heap', async () => { - const [min, mid, max] = constants.uint256; - - await instance['$add(uint256,uint256)'](STORAGE_SLOT, min); - await instance['$add(uint256,uint256)'](STORAGE_SLOT, mid); - await instance['$add(uint256,uint256)'](STORAGE_SLOT, max); - - expect( - await instance.$root_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(max); - - await instance['$remove(uint256,uint256)'](STORAGE_SLOT, max); - - expect( - await instance.$root_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(mid); - - await instance['$remove(uint256,uint256)'](STORAGE_SLOT, mid); - - expect( - await instance.$root_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.equal(min); - }); - - describe('reverts if', () => { - it('index out of bounds', async () => { - await expect( - instance.$root_BinaryHeap_UintHeap.staticCall(STORAGE_SLOT), - ).to.be.revertedWithPanic(PANIC_CODES.ARRAY_ACCESS_OUT_OF_BOUNDS); - }); - }); - }); - - describe('#add(uint256)', () => { - it('sets the parent node such that it is greater than or equal to the values of its children when a node is added', async () => { - for (let index = 0; index < 10; index++) { - const value = randomUint256(); - await instance['$add(uint256,uint256)'](STORAGE_SLOT, value); - const nodes = - await instance.$toArray_BinaryHeap_UintHeap.staticCall( - STORAGE_SLOT, - ); - checkNodes(Array.from(nodes)); - } - }); - - it('returns true if value is added', async () => { - expect( - await instance['$add(uint256,uint256)'].staticCall( - STORAGE_SLOT, - randomUint256(), - ), - ).to.be.true; - }); - - it('returns false if value has already been added', async () => { - const value = randomUint256(); - - await instance['$add(uint256,uint256)'](STORAGE_SLOT, value); - - expect( - await instance['$add(uint256,uint256)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.false; - }); - }); - - describe('#remove(uint256)', () => { - it('sets the parent node such that it is greater than or equal to the values of its children when a node is removed', async () => { - const values: bigint[] = []; - - for (let index = 0; index < 10; index++) { - const value = randomUint256(); - await instance['$add(uint256,uint256)'](STORAGE_SLOT, value); - values.push(value); - } - - for (const value of values) { - await instance['$remove(uint256,uint256)'](STORAGE_SLOT, value); - checkNodes( - await instance.$toArray_BinaryHeap_UintHeap.staticCall( - STORAGE_SLOT, - ), - ); - } - }); - - it('returns true if value is removed', async () => { - const value = randomUint256(); - - await instance['$add(uint256,uint256)'](STORAGE_SLOT, value); - - expect( - await instance['$remove(uint256,uint256)'].staticCall( - STORAGE_SLOT, - value, - ), - ).to.be.true; - }); - - it('returns false if value does not exist', async () => { - expect( - await instance['$remove(uint256,uint256)'].staticCall( - STORAGE_SLOT, - randomUint256(), - ), - ).to.be.false; - }); - }); - - describe('#toArray()', () => { - it('returns the max heap as an array', async () => { - const [min, mid, max] = constants.uint256; - - await instance['$add(uint256,uint256)'](STORAGE_SLOT, min); - await instance['$add(uint256,uint256)'](STORAGE_SLOT, mid); - await instance['$add(uint256,uint256)'](STORAGE_SLOT, max); - - const array = - await instance.$toArray_BinaryHeap_UintHeap.staticCall( - STORAGE_SLOT, - ); - - expect(array.length).to.equal(3); - expect(array).to.deep.equal([max, min, mid]); - }); - }); - }); - }); -}); diff --git a/test/inheritance.ts b/test/inheritance.ts index 157925c6e..049de9593 100644 --- a/test/inheritance.ts +++ b/test/inheritance.ts @@ -323,7 +323,6 @@ describe('Inheritance Graph', () => { 'ECDSA', 'EIP712', 'MerkleProof', - 'BinaryHeap', 'DoublyLinkedList', 'PackedDoublyLinkedList', 'EnumerableMap',