Adopt
Ask AI
Adopt mints one gnome to the caller. Every validation v1 and v2 performed is carried over in the same order with the same messages -- the name charset allowlist, the invisible-letter denylist, the one-gnome-per-address rule, the OriginSend refusal -- because those checks are the output of three audit rounds and re-deriving them from memory is how they get lost.
TWO THINGS CHANGE BECAUSE GNOMES CAN NOW BE SOLD. First, an address that has sold its gnome has no gnome, so it may adopt again -- "one gnome per address" is a statement about the present, not a lifetime count, and adoption is free for a fresh address anyway, so refusing it to a seller would punish only the honest. Second, the starting purse is granted ONCE PER ADDRESS, EVER: only if this address has never held acorns. A seller keeps their purse (acorns belong to the player, ECONOMY.md:65-67), so a re-adopting seller must not be topped back up to acornsStart, and a buyer who already has a purse from an earlier gnome keeps that one. Without this, sell-and-readopt would refill acorns for free.
THE CUSTODY QUESTION IS CLOSED: ONLY A WALLET MAY ADOPT. realms/garden/NOTES.md recorded it in full and reserved it for the owner: cur.Previous().Address() is not restricted to a human wallet, so a realm that called Adopt would become the permanent, unrecoverable owner of a gnome, with no burn, admin or transfer to undo it. v1 and v2 left that open. On 2026-10-11 the owner chose the accident case over the sponsor case -- an orphaned gnome permanently owned by some batching or multicall realm is a real person's lost gnome, and it can never be undone -- so Adopt now refuses any caller that is not a direct wallet call, with the same IsUserCall gate Buy already uses (DESIGN.md section 7.5).
What the gate is, exactly, read from this toolchain's chain/runtime: IsUserCall() is "pkgPath == """, true for a `gnokey maketx call` (or a wallet's MsgCall) straight from a user and false for every code realm, INCLUDING the ephemeral realm a `gnokey maketx run` script executes in (that one is IsUserRun, not IsUserCall). So a sponsor realm, a batching realm and a run script are all refused, and none of them can ever be let back in on this realm: a v4 with an explicit "adopt for" path is how that door would reopen. The refusal comes first, before anything is read or written, so a refused caller gets this reason and not a later one.
A consequence worth stating: since Buy is also wallet-only, NO REALM CAN EVER OWN A GNOME here, by construction. The audit's G-2 worry -- a realm owning and listing a gnome so that Buy pays a price to an address with no banker, where it is burned -- has no remaining path.
NEW IN v4: eyes AND nose. Two integers, eyes in [0, numEyes) and nose in [0, numNoses), checked after the hat and coat so a caller with several mistakes hears them in the order the arguments are written. An id outside its range aborts the whole call and mints nothing -- an unknown face is refused, never defaulted, because a default would silently give every mistyped adoption the same face and a face is permanent. THE REALM DOES NOT CARE HOW THE NUMBERS WERE ARRIVED AT. A client may offer the player a choice, or roll on a weighted table and submit the result, or anything in between; this function records what it is given and validates it, and nothing on chain can tell the two apart. That neutrality is deliberate and argued in realms/garden/v4/DESIGN.md section 3: a realm cannot be edited, so the choice-versus- rarity decision must not be frozen in one. Its honest consequence is stated there too -- rarity on this realm is a property of client discipline, not of the contract, and a raw gnokey caller can always ask for the rarest face. The signature change breaks every existing Adopt caller (the app's live.js builds [name, hat, coat]); v4 DESIGN.md section 4 lists them.
Command
# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.
gnokey maketx call -pkgpath "gno.land/r/g1r4aw43kagaaquhegxw6xr346h9f2qu2ezf0jar/garden/v4" -func "Adopt" -args $'' -args $'' -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "onyx-1" -remote "https://rpc.onyx.testnets.gno.land" ADDRESSgnokey query -remote "https://rpc.onyx.testnets.gno.land" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/g1r4aw43kagaaquhegxw6xr346h9f2qu2ezf0jar/garden/v4" -func "Adopt" -args $'' -args $'' -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "onyx-1" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://rpc.onyx.testnets.gno.land" call.tx