Skip to content

Commit

Permalink
Packed Slot Helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
tom2o17 committed Jun 11, 2024
1 parent 0f40dca commit 9b57f5c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
52 changes: 52 additions & 0 deletions src/FraxTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ abstract contract FraxTest is VmHelper, Test {
uint256[] internal snapShotIds;
function()[] internal setupFunctions;

// ========================================================================
// ~~~~~~~~~~~~~~~~~~ Different State Testing Helpers ~~~~~~~~~~~~~~~~~~~~~
// ========================================================================

modifier useMultipleSetupFunctions() {
if (snapShotIds.length == 0) _;
for (uint256 i = 0; i < snapShotIds.length; i++) {
Expand All @@ -30,6 +34,13 @@ abstract contract FraxTest is VmHelper, Test {
}
}

// ========================================================================
// ~~~~~~~~~~~~~~~~~~~~~~~ Storage Slot Helpers ~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ========================================================================

/// @notice Helper function to dump the storage slots of a contract to the console
/// @param target The target contract whose state we wish to view
/// @param slotsToDump The # of lower storage slots we want to log
function dumpStorageLayout(address target, uint256 slotsToDump) internal view {
console.log("===================================");
console.log("Storage dump for: ", target);
Expand All @@ -41,5 +52,46 @@ abstract contract FraxTest is VmHelper, Test {
}
}

/// @notice Helper function for unpacking low level storage slots
/// @param dataToUnpack The bytes32|uint256 of the slot to unpack
/// @param offset The bits to remove st. the target bits are LSB
/// @param lenOfTarget The length target result in bits
/// @return result The target bits expressed as a uint256
function unpackBits(
uint256 dataToUnpack,
uint256 offset,
uint256 lenOfTarget
) internal pure returns (uint256 result) {
uint256 mask = (1 << lenOfTarget) - 1;
result = (dataToUnpack >> offset) & mask;
}

function unpackBits(
bytes32 dataToUnpack,
uint256 offset,
uint256 lenOfTarget
) internal pure returns (uint256 result) {
uint256 mask = (1 << lenOfTarget) - 1;
result = (uint256(dataToUnpack) >> offset) & mask;
}

function unpackBitsAndLogUint(
uint256 dataToUnpack,
uint256 offset,
uint256 lenOfTarget
) internal pure returns (uint256 result) {
result = unpackBits(dataToUnpack, offset, lenOfTarget);
console.log(result);
}

function unpackBitsAndLogUint(
bytes32 dataToUnpack,
uint256 offset,
uint256 lenOfTarget
) internal pure returns (uint256 result) {
result = unpackBits(dataToUnpack, offset, lenOfTarget);
console.log(result);
}

error VmDidNotRevert(uint256 _snapshotId);
}
26 changes: 24 additions & 2 deletions test/TestSlotDump.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,29 @@ contract TestSlotDump is FraxTest {
address instance;

function testDumpSlots() public {
instance = address(new Bravo());
instance = address(new Charlie());
dumpStorageLayout(instance, 15);
}

function testUnpackSlot() public {
instance = address(new Charlie());
dumpStorageLayout(instance, 15);

bytes32 packedSlot = vm.load(address(instance), bytes32(uint(9)));
uint256 unpacked1 = unpackBits(packedSlot, 0, 96);
uint256 unpacked2 = unpackBits(packedSlot, 96, 160);

/// @notice `unpacked1` is `uint96` expressed as `uint256`
assertEq(22222222222222222222, unpacked1);
assertEq(22222222222222222222, uint96(unpacked1));

/// @notice `unpacked2` is `address` expressed as `uint256`
assertEq(uint256(uint160(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)), unpacked2);
assertEq(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, address(uint160(unpacked2)));
}
}

// ================== Helpers =============
// ================== Helpers ==================

contract Alpha {
address owner = address(0xC0ffee);
Expand All @@ -24,3 +41,8 @@ contract Bravo is Alpha {
uint256[5] gap;
bytes32 someOtherValue = 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA;
}

contract Charlie is Bravo {
uint96 packed1 = 22222222222222222222;
address packed2 = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
}

0 comments on commit 9b57f5c

Please sign in to comment.