I’m working on a token-gated NFT distribution site. I’ve divided up the 256 bits of the token id & I’m using various parts to represent different aspects of a permissioning system. Central to the architecture are role gating tokens. Pretty much every operation is goverened by an associated role that a user can have by::Listen
I’m working on a token-gated NFT distribution site. I’ve divided up the 256 bits of the token id & I’m using various parts to represent different aspects of a permissioning system.
Central to the architecture are role gating tokens. Pretty much every operation is goverened by an associated role that a user can have by possessing a token with a particular id.
Currently I have all my fields defined as a set of constants in a library of the form:
uint8 public constant TEAM_WIDTH = 13; // 13 bits for teams, one bit per team uint8 public constant TEAM_BOUNDARY = uint8(256 - TEAM_WIDTH); // the first bit of the team field uint8 public constant TYPE_WIDTH = 8; // eight bits for a general type uint8 public constant TYPE_BOUNDARY = TEAM_BOUNDARY - TYPE_WIDTH; // first type bit uint8 public constant REQUIREMENT_WIDTH = 3; // single use, valid until / after, etc. uint8 public constant REQUIREMENT_BOUNDARY = TYPE_BOUNDARY - REQUIREMENT_WIDTH; / first // the first 32 bits are a unique sequential counter // (for “vanilla NFTs”, not the ones controlling the operation of the system) // (the operational NFTs use the counter to identify which token they operate on) uint8 public constant COUNTER_WIDTH = 32; uint256 public constant TEAM_MASK = (2**TEAM_WIDTH - 1) << TEAM_BOUNDARY; // 1s in the most significant 13 bits uint256 public constant TYPE_MASK = (2**TYPE_WIDTH - 1) << TYPE_BOUNDARY; // 1s in the 14ᵗʰ–22ⁿᵈ MSBs // ⋮ uint256 public constant COUNTER_MASK = (2**COUNTER_WIDTH - 1);
One of the types of tokens are roles. I’m using an enum
to lay out the bits, and I would like the contract to be the source of truth as to what roles exist.
To this end, I have a function:
function roleNameByIndex(Role index) public pure returns (string memory name) { if(index == Role.Superuser) return "Superuser"; if(index == Role.Minter) return "Minter"; if(index == Role.Caster) return "Caster"; // ⋮ }
And a corresponding function:
function roleIndexForName(string memory roleName) public pure returns (Role role) { bytes32 hash = keccak256(abi.encodePacked(roleName)); if(hash == keccak256(abi.encodePacked('Superuser'))) { return Role.Superuser; } if(hash == keccak256(abi.encodePacked('Minter'))) { return Role.Minter; } if(hash == keccak256(abi.encodePacked('Caster'))) { return Role.Caster; } // ⋮ }
They operate in terms of a Role
enum
that looks like:
enum Role { Reserved0, Superuser, Minter, Caster, // ⋮ Reserved−1 }
All seems well & good. The functions worked when they were directly in the token contract, but moving them to the library seems to have broken them.
To see for yourself:
git clone https://github.com/MetaFam/chievemints.git yarn && yarn hh:node &; yarn hh:test