Skip to content

Instantly share code, notes, and snippets.

@PedroCailleret
Last active July 17, 2022 04:08
Show Gist options
  • Select an option

  • Save PedroCailleret/e95ce73a9c2f6b9df2768feb15d0fe5b to your computer and use it in GitHub Desktop.

Select an option

Save PedroCailleret/e95ce73a9c2f6b9df2768feb15d0fe5b to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.4;
/// @author 0xtr4um4
/// @notice This is a quick demo on how to read custom types (enum) of a struct
/// nested in a mapping from storage using assembly when considering read value
/// to be fetched through not tightly packed/optimized storage slots.
contract AssemblySructGetter {
enum ERC721Type // uint8 => max value: 255 bits = (2^8 - 1)
{
ERC721Minimal, // == 0
ERC721Basic, // == 1
ERC721Whitelist, // == 2
ERC721Lazy // == 3
}
// Ideally we should pack the storage slots to leave last 20 bytes (address) for last;
// but since we are reaching for irregular struct storage reads (i.e., assymetric storage
// slot distribution), we `shr` by 160 bits (20 bytes for the type) and 1 (`uint8` value
// returned from enum type) should follow next. With regularly distributed struct
// storage slots (32 bytes delimited), adding the storage location to itself
// up to the desired point with `and(sload(add(col.slot, 2))` is possible.
struct Collection {
address creator; // 20 bytes = 160 bits
ERC721Type colType; // 32 bytes = 256 bits
bytes32 colSalt; // {...}
uint256 blocknumber; // {...}
}
// passing in uint256 to fill an entire 32 bytes slot
mapping(uint256 => Collection) private colInfo;
constructor() {
bytes32 tokenSalt = keccak256(bytes("string"));
colInfo[255] = Collection(
msg.sender,
ERC721Type.ERC721Basic, // 8 bit value
tokenSalt,
block.number
);
}
/// @dev Cost: 23756 gas
function yulTypeCheck() external view returns(address creator, uint8 pointer /* ERC721Type pointer*/) {
Collection storage col = colInfo[255];
assembly {
let x := sload(col.slot)
creator := and(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
pointer := shr(160, x)
}
}
/// @dev Cost: 24021 gas
function saneTypeCheck() external view returns(address creator, uint8 pointer) {
Collection storage col = colInfo[255];
creator = address(col.creator);
pointer = uint8(col.colType);
return (creator, pointer);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment