|
@@ -263,7 +263,7 @@ Some use cases require more powerful data structures than arrays and mappings of
|
|
|
- xref:api:utils.adoc#EnumerableSet[`EnumerableSet`]: A https://en.wikipedia.org/wiki/Set_(abstract_data_type)[set] with enumeration capabilities.
|
|
|
- xref:api:utils.adoc#EnumerableMap[`EnumerableMap`]: A `mapping` variant with enumeration capabilities.
|
|
|
- xref:api:utils.adoc#MerkleTree[`MerkleTree`]: An on-chain https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] with helper functions.
|
|
|
-- xref:api:utils.adoc#Heap.sol[`Heap`]: A
|
|
|
+- xref:api:utils.adoc#Heap.sol[`Heap`]: A https://en.wikipedia.org/wiki/Binary_heap[binary heap] to store elements with priority defined by a compartor function.
|
|
|
|
|
|
The `Enumerable*` structures are similar to mappings in that they store and remove elements in constant time and don't allow for repeated entries, but they also support _enumeration_, which means you can easily query all stored entries both on and off-chain.
|
|
|
|
|
@@ -461,6 +461,38 @@ await instance.multicall([
|
|
|
]);
|
|
|
----
|
|
|
|
|
|
+=== Memory
|
|
|
+
|
|
|
+The xref:api:utils.adoc#Memory[`Memory`] library provides functions for advanced use cases that require granular memory management. A common use case is to avoid unnecessary memory expansion costs when performing repeated operations that allocate memory in a loop. Consider the following example:
|
|
|
+
|
|
|
+[source,solidity]
|
|
|
+----
|
|
|
+function processMultipleItems(uint256[] memory items) internal {
|
|
|
+ for (uint256 i = 0; i < items.length; i++) {
|
|
|
+ bytes memory tempData = abi.encode(items[i], block.timestamp);
|
|
|
+ // Process tempData...
|
|
|
+ }
|
|
|
+}
|
|
|
+----
|
|
|
+
|
|
|
+Note that each iteration allocates new memory for `tempData`, causing the memory to expand continuously. This can be optimized by resetting the memory pointer between iterations:
|
|
|
+
|
|
|
+[source,solidity]
|
|
|
+----
|
|
|
+function processMultipleItems(uint256[] memory items) internal {
|
|
|
+ Memory.Pointer ptr = Memory.getFreeMemoryPointer(); // Cache pointer
|
|
|
+ for (uint256 i = 0; i < items.length; i++) {
|
|
|
+ bytes memory tempData = abi.encode(items[i], block.timestamp);
|
|
|
+ // Process tempData...
|
|
|
+ Memory.setFreeMemoryPointer(ptr); // Reset pointer for reuse
|
|
|
+ }
|
|
|
+}
|
|
|
+----
|
|
|
+
|
|
|
+This way, memory allocated for `tempData` in each iteration is reused, significantly reducing memory expansion costs when processing many items.
|
|
|
+
|
|
|
+IMPORTANT: Only use these functions after carefully confirming they're necessary. By default, Solidity handles memory safely. Using this library without understanding memory layout and safety may be dangerous. See the https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_memory.html[memory layout] and https://docs.soliditylang.org/en/v0.8.20/assembly.html#memory-safety[memory safety] documentation for details.
|
|
|
+
|
|
|
=== Historical Block Hashes
|
|
|
|
|
|
xref:api:utils.adoc#Blockhash[`Blockhash`] provides L2 protocol developers with extended access to historical block hashes beyond Ethereum's native 256-block limit. By leveraging https://eips.ethereum.org/EIPS/eip-2935[EIP-2935]'s history storage contract, the library enables access to block hashes up to 8,191 blocks in the past, making it invaluable for L2 fraud proofs and state verification systems.
|