Shadow Traits — VendingMachine System
On-chain trait uniqueness via keccak256 hashing. Each Shadow Trait combination can only exist once.
[view source]Overview
The VendingMachine is an upgradeable ERC-721 contract that mints "Mibera Shadow Traits" (MST). It enforces that every trait combination is globally unique — if someone mints a specific set of traits, no one else can ever mint the same combination.
This is the on-chain layer that makes Shadow Traits scarce. The codex documents the visual traits; the VendingMachine enforces their on-chain uniqueness.
[view source]Contract
| Name | Address | Chain | Standard |
|---|---|---|---|
| Mibera Shadows (VendingMachine) | 0x048327A187b944ddac61c6e202BfccD20d17c008 |
Berachain | ERC-721 (UUPS Proxy) |
[view source]Mechanics
Trait Hashing
When a user mints, they pass a _traits string. The contract hashes it:
bytes32 hashedTraits = keccak256(abi.encodePacked(_traits))
The hash is stored in traitsUsed[hash] = true. If that hash already exists, the transaction reverts with AlreadyExists(). This guarantees every Shadow Trait combination is a 1-of-1.
Minting (the shop function)
function shop(string calldata _traits) external payable
- Caller pays exactly
pricein native BERA (reverts withWrongMoney()if not exact) - Trait string is hashed via keccak256
- If hash exists in
traitsUsed, revertAlreadyExists() - Mark hash as used
- Mint sequential token ID to caller
- Transfer full payment to treasury
- Emit
Minted(user, tokenId, traits)event — the trait string is logged on-chain
Checking Uniqueness
function areTraitsUsed(string calldata _traits) external view returns (bool)
Anyone can check if a specific trait combination has already been claimed.
UUPS Proxy Pattern
The contract uses OpenZeppelin's UUPS upgradeable pattern:
- Implementation can be upgraded by the owner
- V2 added
setTreasury()to allow changing the treasury address post-deployment - Storage layout preserved via
uint256[45] __gap
[view source]Key Constants
| Parameter | Value | Notes |
|---|---|---|
| Token name | "Mibera Shadow Traits" | |
| Token symbol | "MST" | |
| Initial price | type(uint256).max |
Effectively disabled until owner sets real price |
| Treasury | Receives 100% of mint proceeds |
[view source]V1 → V2 Changes
The only addition in V2 is setTreasury(address) — allows the owner to redirect mint proceeds to a new treasury address. All other logic is identical.
[view source]Relationship to Main Collection
Shadow Traits are independent tokens — they don't require ownership of a main Mibera NFT. They represent custom trait combinations that anyone can mint (as long as the combination hasn't been claimed). The "shadow" aspect is that these traits exist alongside the generative Mibera traits but on a separate contract.
[view source]Source
- Contract V1:
honey-road/src/VendingMachine.solin mibera-contracts - Contract V2:
honey-road/src/VendingMachineV2.sol - Deployed proxy:
0x048327A187b944ddac61c6e202BfccD20d17c008 - Standard: ERC-721 Upgradeable (UUPS)
- Chain: Berachain (80094)
