Skip to content

Commit 9eb5f1c

Browse files
committed
Add memory utils
1 parent a9161aa commit 9eb5f1c

File tree

5 files changed

+97
-0
lines changed

5 files changed

+97
-0
lines changed

.changeset/dull-students-eat.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'openzeppelin-solidity': minor
3+
---
4+
5+
`Memory`: Add library with utilities to manipulate memory

contracts/utils/Memory.sol

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
/// @dev Memory utility library.
6+
library Memory {
7+
type Pointer is bytes32;
8+
9+
/// @dev Returns a memory pointer to the current free memory pointer.
10+
function getFreePointer() internal pure returns (Pointer ptr) {
11+
assembly ("memory-safe") {
12+
ptr := mload(0x40)
13+
}
14+
}
15+
16+
/// @dev Sets the free memory pointer to a specific value.
17+
///
18+
/// WARNING: Everything after the pointer may be overwritten.
19+
function setFreePointer(Pointer ptr) internal pure {
20+
assembly ("memory-safe") {
21+
mstore(0x40, ptr)
22+
}
23+
}
24+
25+
/// @dev Pointer to `bytes32`.
26+
function asBytes32(Pointer ptr) internal pure returns (bytes32) {
27+
return Pointer.unwrap(ptr);
28+
}
29+
30+
/// @dev `bytes32` to pointer.
31+
function asPointer(bytes32 value) internal pure returns (Pointer) {
32+
return Pointer.wrap(value);
33+
}
34+
}

contracts/utils/README.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t
4040
* {Packing}: A library for packing and unpacking multiple values into bytes32
4141
* {Panic}: A library to revert with https://docs.soliditylang.org/en/v0.8.20/control-structures.html#panic-via-assert-and-error-via-require[Solidity panic codes].
4242
* {Comparators}: A library that contains comparator functions to use with with the {Heap} library.
43+
* {Memory}: A utility library to manipulate memory.
4344

4445
[NOTE]
4546
====

test/utils/Memory.t.sol

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
pragma solidity ^0.8.20;
4+
5+
import {Test} from "forge-std/Test.sol";
6+
import {Memory} from "@openzeppelin/contracts/utils/Memory.sol";
7+
8+
contract MemoryTest is Test {
9+
using Memory for *;
10+
11+
function testSymbolicGetSetFreePointer(bytes32 ptr) public {
12+
Memory.Pointer memoryPtr = ptr.asPointer();
13+
Memory.setFreePointer(memoryPtr);
14+
assertEq(Memory.getFreePointer().asBytes32(), memoryPtr.asBytes32());
15+
}
16+
}

test/utils/Memory.test.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const { ethers } = require('hardhat');
2+
const { expect } = require('chai');
3+
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
4+
5+
async function fixture() {
6+
const mock = await ethers.deployContract('$Memory');
7+
8+
return { mock };
9+
}
10+
11+
describe('Memory', function () {
12+
beforeEach(async function () {
13+
Object.assign(this, await loadFixture(fixture));
14+
});
15+
16+
describe('free pointer', function () {
17+
it('sets memory pointer', async function () {
18+
const ptr = '0x00000000000000000000000000000000000000000000000000000000000000a0';
19+
expect(await this.mock.$setFreePointer(ptr)).to.not.be.reverted;
20+
});
21+
22+
it('gets memory pointer', async function () {
23+
expect(await this.mock.$getFreePointer()).to.equal(
24+
// Default pointer
25+
'0x0000000000000000000000000000000000000000000000000000000000000080',
26+
);
27+
});
28+
29+
it('asBytes32', async function () {
30+
const ptr = ethers.toBeHex('0x1234', 32);
31+
await this.mock.$setFreePointer(ptr);
32+
expect(await this.mock.$asBytes32(ptr)).to.equal(ptr);
33+
});
34+
35+
it('asPointer', async function () {
36+
const ptr = ethers.toBeHex('0x1234', 32);
37+
await this.mock.$setFreePointer(ptr);
38+
expect(await this.mock.$asPointer(ptr)).to.equal(ptr);
39+
});
40+
});
41+
});

0 commit comments

Comments
 (0)