On-chain trait uniqueness via keccak256 hashing. Each Shadow Trait combination can only exist once.
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.
| Name | Address | Chain | Standard |
|---|---|---|---|
| Mibera Shadows (VendingMachine) | 0x048327A187b944ddac61c6e202BfccD20d17c008 |
Berachain | ERC-721 (UUPS Proxy) |
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.
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
function areTraitsUsed(string calldata _traits) external view returns (bool)
Anyone can check if a specific trait combination has already been claimed.
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
| 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 |
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.
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.
- 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)