You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.2 KiB
Solidity
152 lines
4.2 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.0;
|
|
|
|
library SlotHelper {
|
|
uint256 internal constant SLOTDATA_RIGHT_SHIFT = 32;
|
|
uint256 internal constant LEN_OFFSET = 224;
|
|
uint256 internal constant FIRST_SLOT_DATA_SIZE = 28;
|
|
|
|
function putRaw(
|
|
mapping(uint256 => bytes32) storage slots,
|
|
bytes memory datas
|
|
) internal returns (bytes32 mdata) {
|
|
uint256 len = datas.length;
|
|
mdata = encodeMetadata(datas);
|
|
if (len > FIRST_SLOT_DATA_SIZE) {
|
|
bytes32 value;
|
|
uint256 ptr;
|
|
assembly {
|
|
ptr := add(datas, add(0x20, FIRST_SLOT_DATA_SIZE))
|
|
}
|
|
for (
|
|
uint256 i = 0;
|
|
i < (len - FIRST_SLOT_DATA_SIZE + 32 - 1) / 32;
|
|
i++
|
|
) {
|
|
assembly {
|
|
value := mload(ptr)
|
|
}
|
|
ptr = ptr + 32;
|
|
slots[i] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
function encodeMetadata(
|
|
bytes memory data
|
|
) internal pure returns (bytes32 medata) {
|
|
uint256 datLen = data.length;
|
|
uint256 value;
|
|
assembly {
|
|
value := mload(add(data, 0x20))
|
|
}
|
|
|
|
datLen = datLen << LEN_OFFSET;
|
|
value = value >> SLOTDATA_RIGHT_SHIFT;
|
|
|
|
medata = bytes32(value | datLen);
|
|
}
|
|
|
|
function decodeMetadata(
|
|
bytes32 mdata
|
|
) internal pure returns (uint256 len, bytes32 data) {
|
|
len = decodeLen(mdata);
|
|
data = mdata << SLOTDATA_RIGHT_SHIFT;
|
|
}
|
|
|
|
function decodeMetadataToData(
|
|
bytes32 mdata
|
|
) internal pure returns (uint256 len, bytes memory data) {
|
|
len = decodeLen(mdata);
|
|
mdata = mdata << SLOTDATA_RIGHT_SHIFT;
|
|
data = new bytes(len);
|
|
assembly {
|
|
mstore(add(data, 0x20), mdata)
|
|
}
|
|
}
|
|
|
|
function getRaw(
|
|
mapping(uint256 => bytes32) storage slots,
|
|
bytes32 mdata
|
|
) internal view returns (bytes memory data) {
|
|
uint256 datalen;
|
|
(datalen, data) = decodeMetadataToData(mdata);
|
|
|
|
if (datalen > FIRST_SLOT_DATA_SIZE) {
|
|
uint256 ptr = 0;
|
|
bytes32 value = 0;
|
|
assembly {
|
|
ptr := add(data, add(0x20, FIRST_SLOT_DATA_SIZE))
|
|
}
|
|
for (
|
|
uint256 i = 0;
|
|
i < (datalen - FIRST_SLOT_DATA_SIZE + 32 - 1) / 32;
|
|
i++
|
|
) {
|
|
value = slots[i];
|
|
assembly {
|
|
mstore(ptr, value)
|
|
}
|
|
ptr = ptr + 32;
|
|
}
|
|
}
|
|
}
|
|
|
|
function getRawAt(
|
|
mapping(uint256 => bytes32) storage slots,
|
|
bytes32 mdata,
|
|
uint256 memoryPtr
|
|
) internal view returns (uint256 datalen, bool found) {
|
|
bytes32 datapart;
|
|
(datalen, datapart) = decodeMetadata(mdata);
|
|
|
|
// memoryPtr:memoryPtr+32 is allocated for the data
|
|
uint256 dataPtr = memoryPtr;
|
|
assembly {
|
|
mstore(dataPtr, datapart)
|
|
}
|
|
|
|
if (datalen > FIRST_SLOT_DATA_SIZE) {
|
|
uint256 ptr = 0;
|
|
bytes32 value = 0;
|
|
|
|
assembly {
|
|
ptr := add(dataPtr, FIRST_SLOT_DATA_SIZE)
|
|
}
|
|
for (
|
|
uint256 i = 0;
|
|
i < (datalen - FIRST_SLOT_DATA_SIZE + 32 - 1) / 32;
|
|
i++
|
|
) {
|
|
value = slots[i];
|
|
assembly {
|
|
mstore(ptr, value)
|
|
}
|
|
ptr = ptr + 32;
|
|
}
|
|
}
|
|
|
|
found = true;
|
|
}
|
|
|
|
function isInSlot(bytes32 mdata) internal pure returns (bool succeed) {
|
|
return decodeLen(mdata) > 0;
|
|
}
|
|
|
|
function encodeLen(uint256 datalen) internal pure returns (bytes32 res) {
|
|
res = bytes32(datalen << LEN_OFFSET);
|
|
}
|
|
|
|
function decodeLen(bytes32 mdata) internal pure returns (uint256 res) {
|
|
res = uint256(mdata) >> LEN_OFFSET;
|
|
}
|
|
|
|
function addrToBytes32(address addr) internal pure returns (bytes32) {
|
|
return bytes32(uint256(uint160(addr)));
|
|
}
|
|
|
|
function bytes32ToAddr(bytes32 bt) internal pure returns (address) {
|
|
return address(uint160(uint256(bt)));
|
|
}
|
|
}
|