faces.onenft.click

One roll a day, and what you may pin

The roll. Every wallet may roll once per UTC day, in two steps so nobody can peek and retry. commit spends your day, fixes your pins and pays the fee. One block later reveal mixes the hash of the block after your commit with your address and the token number into a 64-bit seed, and the seed decides everything: seven layers, five colours, and whether this roll takes a one of one. The site reveals for you, so you sign once; anyone may reveal for anyone, and a commit nobody reveals just waits. A free roll costs gas and nothing else.

The pins. Twelve things can be pinned: the seven layers (background, top, head, eyes, mouth, accessory, hair or hat) and five colours (skin, hair, ground, top, accent). Layers pin to common or uncommon items only; the pinnable skins are the eleven human tones, all common; the fantasy tones are rare or legendary and come only from luck. Every other colour can be pinned. The price doubles with every pin: 0.0005 ETH for one, 0.001 for two, up to 1.024 for all twelve. 95 percent of the fee goes to the author, 5 percent to the keeper wallet that pays gas for reveals and the treasury's rolls. Rare and legendary items cannot be pinned; they come from luck or not at all.

The layers. 18 background, 14 top, 8 head, 16 eyes, 17 mouth, 24 accessory, 26 hair. Every item has a tier: common, uncommon, rare, legendary. The weight tables live in the contract; the rarity page lists each item's odds per roll. Skin, hair colour, top colour, ground and accent colour are drawn on top of that. 96,574,525,931,520 combinations before the one of ones.

The one of ones. 50 full drawings sit in a pool. Any roll takes one with odds of pool left over tokens left: about 1 in 200 on the first roll, better as the end nears, so on average the whole pool is rolled by the last token. The contract removes a rolled one from the pool; each exists once. See what is left.

The treasury. The author's wallet gets one free roll a day too, with the same luck as everyone. Anyone may trigger it; the site does, at midnight UTC.

The image. A sprite is 32 by 32 pixels of roles, not colours: outline, fill, shade, light, a second fill, white. The token's palette turns roles into colours, so one hair sprite serves every hair colour. Layers composite bottom to top, a rim light lands where a fill sits right of an outline, and the result is one SVG of rects returned as a data: URI by the contract, with no server in between.

The end. Supply stops at 10,000. The image rules can change for faces not yet rolled until the author locks them; a rolled face keeps its renderer forever.

Build it yourself

The generator is in the repository, in TypeScript and in Solidity, with a test that keeps the two byte for byte equal. The draw:

u64 mix(u64 x):
  x += 0x9e3779b97f4a7c15
  x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9
  x = (x ^ (x >> 27)) * 0x94d049bb133111eb
  return x ^ (x >> 31)

seed = keccak(blockhash(commitBlock + 1), wallet, pins, commitBlock, tokenId) as u64
draw(i) = mix(seed + i) mod 10000
for slot in 0..6: item[slot] = walk(WEIGHTS[slot], draw(slot)), or the pin
skin = walk(SKIN_WEIGHTS, draw(7)), or the pin; hair colour, top colour, ground, accent = draw(8..11) mod count, or their pins
lucky = draw(12) < pool size * 10000 / tokens left; one = pool[draw(13) mod pool size]

Everything here is CC0. If you build on it, write to me.

Back to the roll. Every collection: onenft.click.