From 49b6a9e98f2d6ba33713f00996c7849bb696bf15 Mon Sep 17 00:00:00 2001 From: David Meister Date: Fri, 18 Sep 2026 21:12:09 +0000 Subject: [PATCH] test: pin that padMemory rewinds the pointer and makes measurement order immaterial No test failed if padMemory stopped padding or stopped rewinding the free memory pointer. The new test checks the pointer is back where it started after padMemory, and that the linear and walk exports of a store with every list occupied, the most any test in the file allocates after one pad, each cost the same measured first after a pad as measured second. Closes #193 Co-Authored-By: Claude Opus 5 (1M context) --- test/src/lib/LibMemoryKV.gasClaims.t.sol | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/src/lib/LibMemoryKV.gasClaims.t.sol b/test/src/lib/LibMemoryKV.gasClaims.t.sol index 9bb2133..c8ccfbe 100644 --- a/test/src/lib/LibMemoryKV.gasClaims.t.sol +++ b/test/src/lib/LibMemoryKV.gasClaims.t.sol @@ -74,6 +74,30 @@ contract LibMemoryKVGasClaimsTest is Test { } } + /// `padMemory` leaves the free memory pointer where it found it, and the + /// order two measurements are taken in after it changes neither one. The + /// two measured are the most the tests here allocate after one pad: a + /// linear export and a walk export of a store with every list occupied. + /// Each costs the same measured first after a pad as measured second. + function testPadMemoryRewindsThePointerAndMeasurementOrderChangesNeither() public view { + MemoryKV kv = spreadStore(LibMemoryKV.LIST_COUNT); + + uint256 start = Pointer.unwrap(LibPointer.allocatedMemoryPointer()); + padMemory(); + uint256 rewound = Pointer.unwrap(LibPointer.allocatedMemoryPointer()); + + uint256 linearFirst = linearGas(kv); + uint256 walkSecond = walkGas(kv); + + padMemory(); + uint256 walkFirst = walkGas(kv); + uint256 linearSecond = linearGas(kv); + + assertEq(rewound, start, "the free pointer is back where it started"); + assertEq(linearFirst, linearSecond, "the linear export measured first and second"); + assertEq(walkFirst, walkSecond, "the walk export measured first and second"); + } + /// Exporting one pair costs exactly the same whichever list it landed in. /// The walk reaches every list through one mask step and one table lookup, /// so no list is nearer or further than another.