Make sstore()
Great Again!
Instead of using storage variables, just use:
function setTiny(uint256 slot, bytes memory v) internal;
function getTiny(uint256 slot) internal view returns (bool empty, bytes memory v);
Uses only 4-bytes for length
:
uint256 slot = 1;
mapping (uint256 => bytes) map;
map[slot] = new bytes(33) // 3 slots!
setTiny(slot, new bytes(33)) // 2 slots
// storage layout:
// [00000000_00000000...00000000] // null | 0 slot
// [00000000_00000000...00000001] // "empty" | 1 slot
// [00000001_XX000000...00000000] // 1 byte | 1 slot
// [0000001C_XXXXXXXX...XXXXXXXX] // 28 bytes | 1 slot
// [0000001D_XXXXXXXX...XXXXXXXX][XX000000...] // 29 bytes | 2 slots
Before:
function text(bytes32 node, string calldata key) external view returns (string memory) {
return string(records[node][key]);
}
After:
function text(bytes32, string calldata) external view returns (string memory) {
return string(reflect());
}
function reflect() internal view returns (bytes memory) {
return getTiny(uint256(keccak256(msg.data))); // use the incoming call as the key!
}