◀ libregochi

DOCS

How Libregochi works under the pixels: payments, the contract, the rules and the resources it uses on Libre. Written for builders, block producers and anyone who wants to check our work.

The numbers and graphs on this page are generated from the code the game runs, so they change when the rules do.

At a glance

  • A cozy 32×32 pixel pet game on Libre (Antelope/Leap 5). Pets never die; neglected ones get sick and recover with care.
  • Players design their pet in a creator (8 bodies, 16 palettes, 12 eyes, 10 patterns). Nothing is rolled.
  • Care is free: every feed, play, clean and nap is a transaction with 0 fees.
  • Items have fixed prices in LIBRE or BTC, shown before paying. No token of our own, no staking, no farming.
  • Pets, items, stats and XP live in the libregochi contract. There is no game server; the chain is the database.

Architecture

libregochi.com is a static Next.js export on Cloudflare. The browser reads the contract's tables straight from Libre nodes, with failover between endpoints, and the keeper's wallet signs every action. A small Worker handles only /api/* (the waitlist). Each build is fixed to one network, so nobody signs on the wrong chain.

The game has no backend of its own. Reads and writes go to the chain.
SHOW THE NUMBERS
PartWhat it does
libregochi.comStatic site on Cloudflare; a Worker only for /api/*
BrowserDraws the pet and computes live stats with the same rules as the contract
WalletWharfKit: Bitcoin Libre or Anchor; signs each action
Libre nodesget_table_rows reads, 3 mainnet endpoints with failover
libregochiHolds pets, items, players; runs the rules

The rules live in one TypeScript package with integer math only. The C++ contract implements the same rules, and both run the same shared test vectors, so the stats the page shows are the stats the chain stores.

Networks and accounts

NetworkChain IDEndpoints
Libre Mainnet38b1d7815474d0c60683ecbea321d723e83f5da6ae5f1c1f9fecc69d9ba96465https://lb.libre.org https://api.libre.cryptobloks.io https://libre.greymass.com
Libre Testnetb64646740308df2ee06c6b72f34c0f7fa066d940e831f752db2006fcc2b78deehttps://testnet.libre.org https://api.testnet.libre.cryptobloks.io https://libretestnet.greymass.com
  • libregochi: the game contract. Every purchase is a transfer to it.
  • gochivault: receives 70% of LIBRE and 90% of BTC payments. It is the studio's account: it pays for running and building the game, the developer's pay included.
  • eosio.null: burned LIBRE goes here. Nobody holds its keys.
  • Status: the contract goes to testnet first, once the board grants it resources; mainnet follows a testnet play-test and a security review. Progress is on the roadmap.

Paying

Every purchase is a plain token transfer to libregochi with a memo. The Bitcoin Libre wallet shows only from, to, quantity and memo when it asks to sign, so that is everything a purchase needs. The contract reacts to the transfer notification and splits the payment on the spot; it keeps nothing.

LIBRE

BTC

Paid in BTC, 90% goes to gochivault and 10% to the referrer. Bitcoin is never burned. Without a referrer, that share goes to the vault too.
SHOW THE NUMBERS
TokenVaultBurnedReferrer
LIBRE70%20%10%
BTC90%0%10%

MEMOS

adopt:<name>;l=<look>[;r=<referrer>]     an egg designed as <look>
buy:<templateId>[;r=<referrer>]          a wearable, into the inventory
buy:<templateId>:<petId>[;r=<referrer>]  food, care or a helper, used on a pet
rename:<petId>:<name>                    a new name
adopt:Mochi;l=3.12.7.4.gadopt an egg named Mochi, designed as body 3, palette 12, eyes 7, pattern 4, a girl
buy:14;r=alicebuy item 14 (a wearable) into the inventory; alice invited this keeper
buy:9:42buy item 9 (food, care or a helper) and use it on pet 42 right away
rename:42:Sir Mochirename pet 42

The template and pet ids above are examples.

  • Only eosio.token LIBRE (4 decimals) and btc.libre BTC (8 decimals) are accepted, checked by the notification's first receiver, so a look-alike token is refused.
  • The quantity must be exactly the price in the templates table. Anything else is refused and the whole transfer reverts.
  • r=<referrer> is bound once: the first purchase that names a referrer sets it, and it never changes after that. Nobody can invite themselves. The referrer's share goes to the vault when the referrer has no balance row for that token, because creating one would cost the contract RAM.
  • The read-only checkmemo action says what a memo means, or why it would be refused, so wallets and tools can check one before signing. The web app builds memos with the same grammar the contract parses.
  • The starter egg is free: claimstarter, once per keeper, soulbound, for accounts that hold at least 1,000 LIBRE or 1,000 sats, which keeps throwaway accounts from farming eggs.

Prices

Prices are set in US dollars and stored in the contract's templates table as fixed LIBRE and sats amounts. They are checked on the 1st of each month and repriced only when a rate has moved more than 25%, announced a week ahead. Between repricings, the price in LIBRE and sats doesn't move.

The LIBRE rate comes from the swap.libre BTC/LIBRE pool (BLLP) times BTC/USD, as a 7-day median. The on-chain oracle and the price trackers lag behind for LIBRE, so we don't use them.

The first shop, in US dollars. Helpers are optional and limited: 1 XP Snack and 1 Comfy Pillow per pet per day; the Warm Blanket only hatches an egg.
SHOW THE NUMBERS
ItemKindUSD
Kibble bowlfood1¢
Cookiefood2¢
Rice ballfood2¢
Soapcare2¢
Strawberryfood3¢
Pizzafood5¢
Toy ballcare5¢
Comfy Pillowhelper10¢
Medicinecare10¢
XP Snackhelper10¢
Warm Blankethelper25¢
Party hatwearable30¢
Round glasseswearable30¢
Cozy scarfwearable40¢
Flower crownwearable40¢
Star shadeswearable50¢
Witch hatwearable50¢
Raincoatwearable60¢
Tiny wingswearable$1.00
Extra eggpet$1.50

The contract

One contract, libregochi. Every action that changes state calls require_auth on the account it acts for. Purchases aren't actions: the contract reacts to transfers sent to it. It accepts only eosio.token / btc.libre::transfer; any other token is refused, so that transfer fails.

CARE (THE KEEPER SIGNS; FREE)

  • setoffset(keeper: name, minutes: int16)

    Sets the keeper's local day for routines, daily caps and the streak. Once only; the web app sends it with the first care action. Signed by: keeper.

  • feed(keeper: name, pet_id: uint64)

    A free bowl (+30 hunger), 3 per pet per local day. More food is bought. Signed by: keeper.

  • play(keeper: name, pet_id: uint64)

    +20 happiness, −10 energy; once an hour. Signed by: keeper.

  • clean(keeper: name, pet_id: uint64)

    Hygiene back to 100; every 2 hours. Signed by: keeper.

  • sleep(keeper: name, pet_id: uint64)

    A nap: energy comes back at 25 an hour until it's full, and the pet wakes on its own. Signed by: keeper.

  • pet(keeper: name, pet_id: uint64, taps: uint16)

    Petting from the browser, synced at most every 4 hours. Adds happiness and a little capped XP; not a care action for the streak. Signed by: keeper.

  • minigame(keeper: name, pet_id: uint64, game: uint8, score: uint32)

    A finished skill game. XP is capped per play and per day, so a made-up score gains nothing extra. Signed by: keeper.

STARTER EGG

  • claimstarter(keeper: name, pet_name: string, look: string)

    The free starter egg: one per keeper, soulbound, a daily cap for everyone together, and a little LIBRE or BTC in the account. Signed by: keeper.

WEARABLES AND GIFTS

  • equip(keeper: name, pet_id: uint64, item_id: uint64)

    Puts a wearable on a pet; whatever was in that slot goes back to the inventory. Signed by: keeper.

  • unequip(keeper: name, item_id: uint64)

    Takes a wearable off. Signed by: keeper.

  • gift(from: name, to: name, pet_ids: uint64[], item_ids: uint64[], memo: string)

    Gives pets and items to another keeper for free. Soulbound ones can't be given; a pet keeps what it wears, except soulbound items. Signed by: from.

READ-ONLY

  • checkmemo(memo: string)

    Returns what a memo means, or why it would be refused. Wallets and tools can check a memo with it before signing. Signed by: none (read-only).

ADMIN (ON MAINNET, SIGNING REQUESTS THE OWNER SIGNS)

  • setconfig(vault: name, hatch_delay_sec: uint32, starters_per_day: uint32, bodies: uint8, palettes: uint8, eyes: uint8)

    Game settings. On mainnet every admin action is a signing request the owner signs. Signed by: libregochi.

  • settemplate(tpl: template_row)

    Adds or reprices a shop item. An item's kind and slot never change, and `sold` is counted by the contract. Signed by: libregochi.

  • pause(paused: bool)

    Stops or resumes purchases, starter eggs, care, equipping and gifts, for incidents. The contract starts paused. Signed by: libregochi.

TABLES

Every table is in scope libregochi. Rows have a bounded size: names are at most 16 characters, and daily counters are keyed by day number and overwritten, never appended to.

  • config key singleton

    Game settings.

    7 FIELDS
    pausedbool
    vaultnamereceives the vault share
    hatch_delay_secuint32
    starters_per_dayuint32free starter eggs, all keepers together
    bodiesuint8creator option counts
    palettesuint8
    eyesuint8
  • state key singleton

    Counters for new ids, which are never reused.

    4 FIELDS
    next_pet_iduint64
    next_item_iduint64
    starter_dayuint32UTC day number of the counter below
    starters_todayuint32
  • templates key id

    Everything the shop sells, at fixed prices in both currencies.

    16 FIELDS
    iduint641 = egg, 2 = rename
    keystringcatalog key, e.g. xp-snack
    kinduint81 food, 2 care, 3 helper, 4 streak, 5 egg, 6 wearable, 7 service
    slotuint8wearables: 1 head, 2 face, 3 body, 4 back
    min_leveluint8
    price_libreint64LIBRE units, 4 decimals
    price_satsint64BTC units, 8 decimals
    hungerint8stat effects when used, −100..100
    happinessint8
    energyint8
    hygieneint8
    xpuint16
    max_supplyuint320 = unlimited
    solduint32
    on_salebool
    specialuint80 none, 1 medicine, 2 XP Snack, 3 Comfy Pillow, 4 Warm Blanket
  • players key account

    One row per keeper.

    15 FIELDS
    accountname
    referrernamebound once; empty = none
    utc_offset_minint16
    offset_setbool
    starter_claimedbool
    joineduint32
    streak_daysuint16
    streak_last_dayuint32local day number
    freezesuint8
    broken_dayuint32
    days_beforeuint16the streak before a break, for repair
    pets_owneduint16at most 30
    items_owneduint16at most 300
    care_dayuint32
    care_todayuint8care actions toward today's streak day
  • pets key id · index byowner (owner)

    One row per pet, fixed size. Stats are stored at last_update and decay is computed when read or acted on.

    47 FIELDS
    iduint64
    ownername
    name_textstring
    bodyuint8the look, chosen by the keeper
    paletteuint8
    eyesuint8
    patternuint8
    genderuint80 boy, 1 girl
    genuint16
    tradableboolfalse for the starter
    createduint32
    hatch_atuint32
    hungeruint80–100 at last_update
    happinessuint8
    energyuint8
    hygieneuint8
    last_updateuint32
    asleep_untiluint32
    neglect_sinceuint320 = cared for
    sick_sinceuint320 = healthy
    good_sinceuint32start of the current run of good care
    xpuint32
    xp_dayuint32local day of the counters below
    xp_careuint8today's XP per capped source
    xp_routineuint8
    xp_minigameuint8
    xp_pettinguint8
    xp_healthyuint8
    plays_todayuint8
    bowls_todayuint8
    routines_todayuint8bit 0 morning, bit 1 bedtime
    snacks_todayuint8
    pillows_todayuint8
    last_playuint32
    last_cleanuint32
    last_petuint32
    cs_minigamesuint16care-style counters for this stage
    cs_pettinguint16
    cs_cleaninguint16
    cs_feedinguint16
    cs_napsuint16
    style_teenuint8
    style_adultuint8
    worn_headuint64item ids; 0 = nothing
    worn_faceuint64
    worn_bodyuint64
    worn_backuint64
  • items key id · index byowner (owner)

    Wearables and other kept items.

    6 FIELDS
    iduint64
    ownername
    template_iduint64
    pet_iduint64the pet wearing it; 0 = in the inventory
    serialuint32limited editions only
    tradablebool

Once the contract is deployed, read a keeper's pets from any node, for example:

curl -s https://lb.libre.org/v1/chain/get_table_rows \
  -H 'content-type: application/json' \
  -d '{"code":"libregochi","scope":"libregochi","table":"pets",
       "index_position":2,"key_type":"name",
       "lower_bound":"alice","upper_bound":"alice","json":true}'

Stats in a row are as stored at last_update. Decay since then is computed, not stored: the rules below give the current values, the same way the contract settles a pet before every action.

Game rules

  • Stats run 0–100 and fall every hour: hunger 3, happy 2, energy 3, clean 2. A nap brings energy back at 25 an hour.
  • Free care: 3 bowls a day, play every 1 h, a bath every 2 h, petting synced every 4 h.
  • Hunger or hygiene at zero for 24 h makes a pet sick. Medicine cures it at once, or 12 h in a row of good care (hunger and hygiene at least 50) cures it for free. It never dies.
  • Days are the keeper's local days, from a time zone they set once (setoffset).

LEFT ALONE

Nobody comes: hunger hits zero after 33 h 20 min, and 24 h later, at 57 h 20 min, the pet is sick. Energy falls as fast as hunger and happy as fast as clean, so their lines are dashed.
SHOW THE NUMBERS
HourHungerHappyEnergyClean
0100100100100
682888288
1264766476
1846644664
2428522852
3010401040
36028028
42016016
480404
540000
600000
660000
720000

CARED FOR

Three short visits a day (8:00, 14:00, 21:00), free care only: hunger and hygiene never drop below 52, well above the good-care line.
SHOW THE NUMBERS
HourHungerClean
0100100
68288
87684
810084
128876
148272
1410072
188864
217958
21100100
249194
307382
326778
329778
368570
387966
3810066
428858
457952
45100100
489194
547382
566778
569778
608570
627966
6210066
668858
697952
69100100
729194

XP AND LEVELS

  • XP comes from care, routines, petting, minigames and healthy days, and from one paid helper, the XP Snack (+25 XP, 1 per pet per day, not while sick). The free sources need the pet well (no stat under 20, not sick) and each has a daily cap per pet: care 40, routine 10, minigame 60, petting 10, healthy 10.
  • Routines: +5 for looking after the pet between 6:00 and 10:00, and again between 20:00 and midnight, local time. +10 for the first action of each day while the pet is well.
  • Minigames are skill only: up to 30 XP a play for 3 plays a day, and 60 a day at most. Scores are self-reported, which is why the caps exist: a made-up score gains no more than a good one.
  • Streak: a day with 3 care actions (feed, play, clean, sleep) counts. Each streak day adds +10% to care XP, up to +50%. A free freeze comes every 7 streak days, at most 2 held.
Total XP for each level: 12 · n · (n − 1). Teen at level 5, adult at 15, up to level 99.
SHOW THE NUMBERS
LevelTotal XP
10
224
372
4144
5240
6360
7504
8672
9864
101,080
111,320
121,584
131,872
142,184
152,520
162,880
173,264
183,672
194,104
204,560
215,040
225,544
236,072
246,624
257,200
267,800
278,424
289,072
299,744
3010,440
5 kinds of keeper over 60 days, from the same pace simulation we tune the rules with. Buying helpers ($27.00 over 60 days, counting the Double XP Hour and Arcade Token planned for later) gets a daily keeper to adult on day 14 instead of 22, and to level 31 instead of 24. The daily caps limit how far that goes; free care alone still gets there.
SHOW THE NUMBERS
DayDaily, freeDaily, misses 1 in 10Casual, once a dayDaily, buys helpersWeekends only
133141
577391
101094123
1512126154
2014136184
2516157205
3017178226
3518188237
4020199257
45212010277
50222110288
55232311298
60242311318

RAM and CPU

The contract pays the RAM for every row it creates. Players can't: new Libre accounts get 5,120 bytes and there's no RAM market. Purchases are handled in a transfer notification, where Leap's RAM_RESTRICTIONS doesn't let a contract bill the sender. And an extra action just to pay for RAM wouldn't read clearly on the wallet's signing sheet.

So nobody can drain it:

  • rows have a bounded size;
  • at most 30 pets and 300 items per keeper, and at most 10 pets and 10 items per gift;
  • free starter eggs have a daily cap for everyone together.
The 2.00 MB we ask the board for on mainnet: the code takes 1.14 MB (Leap bills code at 10× its size), then a keeper with 2 pets and 3 wearables takes about 1.7 KB. That is room for about 500 keepers. We ask for more in small steps once usage passes 80%, and publish the numbers.
SHOW THE NUMBERS
Bytes
Mainnet ask2,000,000
Contract code and ABI1,136,438
One keeper (2 pets, 3 items)1,723
Keepers that fit501
Ask for more at1,600,000

CPU and NET: the game is designed for at most 30 small transactions per keeper a day, each well under a millisecond, within what a Libre account with a weight of 1 gets (about 430 ms of CPU a day).

Nothing left to chance

  • Pets are designed by the keeper, never rolled.
  • Prices are fixed and shown before paying. Nothing paid for is decided by chance: no loot boxes, no draws, no gacha. Boxes, when they come, show their contents before purchase.
  • Surprise comes from timing and published calendars. Nothing paid for or awarded depends on chance, so there is no draw to audit. Purely cosmetic moments, like the weather, may vary; they award nothing.
  • Leaderboards give badges only. Contests are free to enter, judged by a named jury, with cosmetic prizes.

Security and keys

  • require_auth on every action; only the two accepted tokens; exact prices; 128-bit split math with the remainder to the vault.
  • The contract uses no host functions Libre hasn't activated. The build fails if one sneaks in.
  • Tests run the real contract in Vert against mainnet's token contracts, including an attacker contract that forwards fake transfers.
  • No chain keys in code or CI. Mainnet deploys and admin actions are signing requests the owner signs in their own wallet. The contract starts paused and can be paused in an incident.

Coming at launch

  • The contracts and rules go public, with a reproducible build and the WASM hash, so anyone can check that the code on chain is the code we publish.
  • An external security review before mainnet.
  • Questions or a bug? Email hello@libreslav.com. Libregochi is made by Libreslav, a Libre block producer.

Canonical address: https://libregochi.com/docs