Skip to content

Commit 2a0fb7e

Browse files
committed
Add docs
1 parent 2d397f4 commit 2a0fb7e

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed

contracts/utils/Memory.sol

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

33
pragma solidity ^0.8.20;
44

5-
/// @dev Memory utility library.
5+
/// @dev Utilities to manipulate memory.
6+
///
7+
/// Memory is a contiguous and dynamic byte array in which Solidity stores non-primitive types.
8+
/// This library provides functions to manipulate pointers to this dynamic array.
9+
///
10+
/// WARNING: When manipulating memory, make sure to follow the Solidity documentation
11+
/// guidelines for https://docs.soliditylang.org/en/v0.8.20/assembly.html#memory-safety[Memory Safety].
612
library Memory {
713
type Pointer is bytes32;
814

docs/modules/ROOT/pages/utilities.adoc

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ Some use cases require more powerful data structures than arrays and mappings of
189189
- xref:api:utils.adoc#EnumerableSet[`EnumerableSet`]: A https://en.wikipedia.org/wiki/Set_(abstract_data_type)[set] with enumeration capabilities.
190190
- xref:api:utils.adoc#EnumerableMap[`EnumerableMap`]: A `mapping` variant with enumeration capabilities.
191191
- xref:api:utils.adoc#MerkleTree[`MerkleTree`]: An on-chain https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] with helper functions.
192-
- xref:api:utils.adoc#Heap.sol[`Heap`]: A
192+
- 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.
193193

194194
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.
195195

@@ -386,3 +386,37 @@ await instance.multicall([
386386
instance.interface.encodeFunctionData("bar")
387387
]);
388388
----
389+
390+
=== Memory
391+
392+
The `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 iterating over a section of the code that allocates new memory. Consider the following example:
393+
394+
[source,solidity]
395+
----
396+
function callFoo(address target) internal {
397+
bytes memory callData = abi.encodeWithSelector(
398+
bytes4(keccak256("foo()"))
399+
)
400+
(bool success, /* bytes memory returndata */) = target.call(callData);
401+
require(success);
402+
}
403+
----
404+
405+
Note the function allocates memory for both the `callData` argument and for the returndata even if it's ignored. As such, it may be desirable to reset the free memory pointer after the end of the function.
406+
407+
[source,solidity]
408+
----
409+
function callFoo(address target) internal {
410+
Memory.Pointer ptr = Memory.getFreePointer(); // Cache pointer
411+
bytes memory callData = abi.encodeWithSelector(
412+
bytes4(keccak256("foo()"))
413+
)
414+
(bool success, /* bytes memory returndata */) = target.call(callData);
415+
require(success);
416+
Memory.setFreePointer(ptr); // Reset pointer
417+
}
418+
----
419+
420+
In this way, new memory will be allocated in the space where the `returndata` and `callData` used to be, potentially reducing memory expansion costs by shrinking the its size at the end of the transaction and resulting in gas savings.
421+
422+
IMPORTANT: By default, Solidity handles memory safely. Using this library without understanding how memory works may be dangerous. Consider thoroughly reading the Solidity documentation about the https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_memory.html[memory layout] and how the language defines https://docs.soliditylang.org/en/v0.8.20/assembly.html#memory-safety[memory safety].

test/utils/Memory.t.sol

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ contract MemoryTest is Test {
99
using Memory for *;
1010

1111
function testSymbolicGetSetFreePointer(bytes32 ptr) public {
12-
Memory.Pointer memoryPtr = ptr.asPointer();
13-
Memory.setFreePointer(memoryPtr);
14-
assertEq(Memory.getFreePointer().asBytes32(), memoryPtr.asBytes32());
12+
Memory.setFreePointer(ptr.asPointer());
13+
assertEq(Memory.getFreePointer().asBytes32(), ptr);
1514
}
1615
}

0 commit comments

Comments
 (0)