Skip to content

Commit 860e5a8

Browse files
committed
up
1 parent 6bb96d5 commit 860e5a8

File tree

2 files changed

+74
-20
lines changed

2 files changed

+74
-20
lines changed

contracts/utils/Memory.sol

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ library Memory {
4747
}
4848
}
4949

50-
/// @dev Extracts a `bytes1` from a `Pointer`. `offset` starts from the most significant byte.
50+
/**
51+
* @dev Extracts a `bytes1` from a `Pointer`. `offset` starts from the most significant byte.
52+
*
53+
* NOTE: Will return `0x00` if `offset` is larger or equal to `32`.
54+
*/
5155
function extractByte(Pointer ptr, uint256 offset) internal pure returns (bytes1 v) {
5256
bytes32 word = extractWord(ptr);
5357
assembly ("memory-safe") {
@@ -67,22 +71,22 @@ library Memory {
6771
return asPointer(bytes32(asUint256(ptr) + offset));
6872
}
6973

70-
/// @dev `Pointer` to `bytes32`.
74+
/// @dev `Pointer` to `bytes32`. Expects a pointer to a properly ABI-encoded `bytes` object.
7175
function asBytes32(Pointer ptr) internal pure returns (bytes32) {
7276
return Pointer.unwrap(ptr);
7377
}
7478

75-
/// @dev `Pointer` to `uint256`.
79+
/// @dev `Pointer` to `uint256`. Expects a pointer to a properly ABI-encoded `bytes` object.
7680
function asUint256(Pointer ptr) internal pure returns (uint256) {
7781
return uint256(asBytes32(ptr));
7882
}
7983

80-
/// @dev `bytes32` to `Pointer`.
84+
/// @dev `bytes32` to `Pointer`. Expects a pointer to a properly ABI-encoded `bytes` object.
8185
function asPointer(bytes32 value) internal pure returns (Pointer) {
8286
return Pointer.wrap(value);
8387
}
8488

85-
/// @dev `bytes` to `Pointer`.
89+
/// @dev Returns a `Pointer` to the `value`'s header (i.e. includes the length word).
8690
function asPointer(bytes memory value) internal pure returns (Pointer) {
8791
bytes32 ptr;
8892
assembly ("memory-safe") {
@@ -91,7 +95,7 @@ library Memory {
9195
return asPointer(ptr);
9296
}
9397

94-
/// @dev `Pointer` to `bytes`.
98+
/// @dev `Pointer` to `bytes`. Expects a pointer to a properly ABI-encoded `bytes` object.
9599
function asBytes(Pointer ptr) internal pure returns (bytes memory b) {
96100
assembly ("memory-safe") {
97101
b := ptr

test/utils/Memory.test.js

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,78 @@ describe('Memory', function () {
1414
});
1515

1616
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;
17+
it('sets free memory pointer', async function () {
18+
const ptr = ethers.toBeHex(0xa0, 32);
19+
await expect(this.mock.$setFreePointer(ptr)).to.not.be.reverted;
2020
});
2121

22-
it('gets memory pointer', async function () {
23-
expect(await this.mock.$getFreePointer()).to.equal(
24-
// Default pointer
25-
'0x0000000000000000000000000000000000000000000000000000000000000080',
22+
it('gets free memory pointer', async function () {
23+
await expect(this.mock.$getFreePointer()).to.eventually.equal(
24+
ethers.toBeHex(0x80, 32), // Default pointer
2625
);
2726
});
27+
});
2828

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);
29+
it('extractWord extracts a word', async function () {
30+
const ptr = await this.mock.$getFreePointer();
31+
await expect(this.mock.$extractWord(ptr)).to.eventually.equal(ethers.toBeHex(0, 32));
32+
});
33+
34+
it('extractByte extracts a byte', async function () {
35+
const ptr = await this.mock.$getFreePointer();
36+
await expect(this.mock.$extractByte(ptr, 0)).to.eventually.equal(ethers.toBeHex(0, 1));
37+
});
38+
39+
it('contentPointer', async function () {
40+
const data = ethers.toUtf8Bytes('hello world');
41+
const result = await this.mock.$contentPointer(data);
42+
expect(result).to.equal(ethers.toBeHex(0xa0, 32)); // 0x80 is the default free pointer (length)
43+
});
44+
45+
describe('addOffset', function () {
46+
it('addOffset', async function () {
47+
const basePtr = ethers.toBeHex(0x80, 32);
48+
const offset = 32;
49+
const expectedPtr = ethers.toBeHex(0xa0, 32);
50+
51+
await expect(this.mock.$addOffset(basePtr, offset)).to.eventually.equal(expectedPtr);
3352
});
3453

35-
it('asPointer', async function () {
54+
it('addOffsetwraps around', async function () {
55+
const basePtr = ethers.toBeHex(0x80, 32);
56+
const offset = 256;
57+
const expectedPtr = ethers.toBeHex(0x180, 32);
58+
await expect(this.mock.$addOffset(basePtr, offset)).to.eventually.equal(expectedPtr);
59+
});
60+
});
61+
62+
describe('pointer conversions', function () {
63+
it('asBytes32 / asPointer', async function () {
3664
const ptr = ethers.toBeHex('0x1234', 32);
37-
await this.mock.$setFreePointer(ptr);
38-
expect(await this.mock.$asPointer(ptr)).to.equal(ptr);
65+
await expect(this.mock.$asBytes32(ptr)).to.eventually.equal(ptr);
66+
await expect(this.mock.$asPointer(ethers.Typed.bytes32(ptr))).to.eventually.equal(ptr);
67+
});
68+
69+
it('asBytes / asPointer', async function () {
70+
const ptr = await this.mock.$asPointer(ethers.Typed.bytes(ethers.toUtf8Bytes('hello world')));
71+
expect(ptr).to.equal(ethers.toBeHex(0x80, 32)); // Default free pointer
72+
await expect(this.mock.$asBytes(ptr)).to.eventually.equal(ethers.toBeHex(0x20, 32));
73+
});
74+
75+
it('asUint256', async function () {
76+
const value = 0x1234;
77+
const ptr = ethers.toBeHex(value, 32);
78+
await expect(this.mock.$asUint256(ptr)).to.eventually.equal(value);
79+
});
80+
});
81+
82+
describe('memory operations', function () {
83+
it('copy', async function () {
84+
await expect(this.mock.$copy(ethers.toBeHex(0x80, 32), ethers.toBeHex(0xc0, 32), 32)).to.not.be.reverted;
85+
});
86+
87+
it('copy with zero length', async function () {
88+
await expect(this.mock.$copy(ethers.toBeHex(0x80, 32), ethers.toBeHex(0xc0, 32), 0)).to.not.be.reverted;
3989
});
4090
});
4191
});

0 commit comments

Comments
 (0)