Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/kind-planets-cough.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`StorageSlot`: Add storage slot derivation tooling and typed-slot representation with transient storage support.
16 changes: 16 additions & 0 deletions contracts/mocks/StorageSlotMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import {StorageSlot} from "../utils/StorageSlot.sol";
contract StorageSlotMock {
using StorageSlot for *;

function erc1967slot(string memory path) public pure returns (bytes32) {
return path.erc1967slot();
}

function erc7201slot(string memory path) public pure returns (bytes32) {
return path.erc7201slot();
}

function setBooleanSlot(bytes32 slot, bool value) public {
slot.getBooleanSlot().value = value;
}
Expand All @@ -23,6 +31,10 @@ contract StorageSlotMock {
slot.getUint256Slot().value = value;
}

function setInt256Slot(bytes32 slot, int256 value) public {
slot.getInt256Slot().value = value;
}

function getBooleanSlot(bytes32 slot) public view returns (bool) {
return slot.getBooleanSlot().value;
}
Expand All @@ -39,6 +51,10 @@ contract StorageSlotMock {
return slot.getUint256Slot().value;
}

function getInt256Slot(bytes32 slot) public view returns (int256) {
return slot.getInt256Slot().value;
}

mapping(uint256 key => string) public stringMap;

function setStringSlot(bytes32 slot, string calldata value) public {
Expand Down
24 changes: 6 additions & 18 deletions contracts/utils/Arrays.sol
Original file line number Diff line number Diff line change
Expand Up @@ -361,15 +361,11 @@ library Arrays {
*/
function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
slot := arr.slot
}
return slot.getAddressSlot();
return slot.deriveArray().offset(pos).getAddressSlot();
}

/**
Expand All @@ -379,15 +375,11 @@ library Arrays {
*/
function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
slot := arr.slot
}
return slot.getBytes32Slot();
return slot.deriveArray().offset(pos).getBytes32Slot();
}

/**
Expand All @@ -397,15 +389,11 @@ library Arrays {
*/
function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
bytes32 slot;
// We use assembly to calculate the storage slot of the element at index `pos` of the dynamic array `arr`
// following https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays.

/// @solidity memory-safe-assembly
assembly {
mstore(0, arr.slot)
slot := add(keccak256(0, 0x20), pos)
slot := arr.slot
}
return slot.getUint256Slot();
return slot.deriveArray().offset(pos).getUint256Slot();
}

/**
Expand Down
Loading