Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

budgets package

Overview

Realm budgets is a delegated-budget treasury in GNOT: an owner funds a pool, grants named delegates a standing, rate-limited, revocable authority to spend from it, and each delegate then draws within that authority with no further approval from anyone.

WHY THIS EXISTS (see DISCOVERY.md): every disbursement path on either live chain is one of three shapes — a fresh group decision per spend (this portfolio's treasury_board, gno.land's r/gov/dao/treasury, the mainnet bubbletreasury), a fixed schedule (vesting), or a pull against an already-settled entitlement (fee_split, revshare, crowdfund, subscriptions). None of them lets one party spend another's money at its own discretion within a bound. That is the gap, and bubbletreasury — a real mainnet treasury that hand-rolled a sliding spend window inside the realm, with every spend still a token-holder proposal — is the evidence someone wanted it.

It is also, deliberately, the FIRST CONSUMER of spendbook on any chain. A primitive with no consumer has two properties unproven no matter how many unit tests pass: that its API is usable from a realm, and that its state survives across transactions. Only a realm can answer either, and this one is the answer.

COMPOSITION: spending authority is delegated entirely to spendbook (anchored windows, lifetime caps, expiry, one-sided amendments, revocation), coin movement to coinio, per-delegate credit and the fee pot to feeledger, ordered storage to p/nt/avl/v0, and free-text render output to p/nt/markdown/sanitize/v0. This realm owns only the pool accounting, the grant records, and the solvency rule.

What a budget is, and what it is not

A budget is AUTHORITY, not a reservation. Three grants of 100 against a pool of 100 are all three valid, and the first delegate to draw gets the money. This is not a defect to be fixed by reserving funds: a reservation would make an owner unable to grant a standing allowance without pre-committing the capital, which is the whole convenience being bought. What the realm guarantees instead is that it never PROMISES what it does not HOLD:

Example
1Draw refuses unless amount <= the owner's own unspent pool.

So a delegate is told "no" at draw time rather than credited with something unclaimable. The pool is the solvency bound and it is per-owner, which is strictly stronger than a realm-wide check: one owner's grants can never reach another owner's funds.

Credit, then pull

Draw moves nothing. It consumes the allowance, debits the owner's pool, and credits the delegate in the ledger; the delegate then signs a separate Claim to receive the coins. This is not ritual. If Draw paid out directly, a failing payout inside the same transaction would leave a consumed allowance with no money delivered, or force the allowance consumption to happen after an effect — and spendbook's own consumer contract item 3 says state first, effect second, for exactly that reason. Splitting it also means a delegate can draw repeatedly and claim once, which is cheaper than claiming per draw.

LIFECYCLE

Example
 1Fund (owner, +send)       : adds real coins to the caller's own pool.
 2                            Anyone may fund; funding makes you an
 3                            owner. Minimum MinFunding.
 4WithdrawPool (owner)      : pulls unspent pool back out, any amount,
 5                            any time. See "the owner can always
 6                            leave" below.
 7WithdrawPoolAll (owner)   : the whole pool.
 8Grant (owner)             : opens one spendbook allowance for one
 9                            delegate and returns the grant id. The
10                            draw fee is snapshotted here.
11Amend (owner)             : changes the grant's terms. Tighter-or-
12                            equal applies now; looser waits for the
13                            next window boundary. PeriodLength is
14                            NOT a parameter — spendbook makes it
15                            immutable and this realm makes that
16                            structural.
17Revoke (owner)            : immediate, and the id is never reused.
18Draw (DELEGATE)           : consumes authority, debits the pool,
19                            credits the delegate net of the fee.
20Claim (DELEGATE)          : pays the delegate's whole credit out.
21Reap (ANYONE)             : removes an EXPIRED grant, freeing its
22                            slot. Permissionless because an expired
23                            allowance can authorize nothing, so
24                            removing it takes nothing from anyone.
25WithdrawFees (ANYONE)     : pays the fee pot to the compile-time
26                            FeeCollector. Fixed destination, so
27                            there is nothing to steer.
28SweepSurplus (ANYONE)     : out-of-band coins to the FeeCollector,
29                            never touching tracked liabilities.

The owner can always leave, and that is the design

WithdrawPool has no lock, no notice period, and no check against outstanding grants. An owner can empty the pool under a live grant and the delegate's next Draw will fail on solvency. This is stated plainly rather than buried: the money is the owner's, Revoke is the clean way to end a relationship, and a realm that could trap an owner's capital behind a grant they regret would be a worse realm. A delegate who needs a guarantee of funds does not want a budget — they want escrow, which is a different artifact.

What the owner CANNOT do is undo work already authorized: credit already drawn into the ledger is the delegate's, and Revoke does not claw it back. Revoking a grant ends future authority only.

THE FEE, precisely

feeBps is snapshotted into the grant at Grant time from the compile-time DrawFeeBps, so a delegate's terms are fixed when the grant is created and visible in GrantInfo from that moment. The fee is charged ONCE per draw, on the gross amount, with feeledger's floor rounding (rounding favors the delegate). The owner's pool is debited the GROSS amount and the delegate is credited the net — the fee is paid by the owner out of the budget, not taken out of the delegate's authority, so a grant of PerPeriod means PerPeriod of the owner's money leaves the pool per window, which is the figure an owner actually cares about bounding. The ledger is constructed with the compile-time MaxFeeBps cap, so a fee above the cap is refused by the primitive, not by a check in this file. There is no fee on funding, on withdrawing an unspent pool, or on claiming.

THERE IS NO ADMIN

The fee rate, the fee collector, every bound and every cap are compile-time constants. No address can change terms, pause the realm, touch a pool it did not fund, or move a grant it did not create. The deployer has no privilege of any kind after deployment.

MONETARY INVARIANT (conservation)

Let H be the ugnot held at this realm's address, P the sum of all owner pools (tracked O(1) as totalPooled), L the ledger's liabilities (unclaimed delegate credit plus the fee pot), and S >= 0 the out-of-band surplus:

Example
1H == P + L + S

Every transition moves value between exactly two terms inside one transaction. Fund raises H and P together (coinio.Receive is the receipt-guaranteed shape). WithdrawPool debits P before the identical amount leaves H. Draw moves gross out of P and into L, split into the delegate's credit and the fee — H does not move at all, which is why Draw has no payout to fail. Claim and WithdrawFees debit L before their payout. Any panic aborts the whole transaction; this realm never issues or removes coins.

ONLY GNOT IS ACCEPTED

Fund rejects any envelope that is not exactly one positive ugnot coin (coinio.Receive). Every other entrypoint rejects attached coins outright rather than converting them into sweepable surplus.

AUTHORIZATION

Every identity is derived from the crossing entrypoint's cur.Previous().Address(). No function takes a caller identity as a parameter, so funding another owner's pool, drawing another delegate's budget, claiming another delegate's credit, or amending a grant you do not own is impossible by construction. This is spendbook consumer contract item 2, closed structurally.

The clock is runtime.ChainHeight(), never an argument. That is spendbook consumer contract item 1: a realm that let a caller choose `now` would have handed the delegate the power to roll the window at will, defeating every cap in the primitive.

STORAGE

A pool entry is paid for by the owner's own funding transaction; a grant record and its allowance by the owner's Grant. Revoke and Reap both remove the grant record and the allowance in the same call, and the chain refunds the freed storage deposit to the transaction that frees it — which is the standing incentive to call Reap on someone else's expired grant.

Function

PoolOf

func PoolOf(addr address) int64
Ask AI Claude ChatGPT

PoolOf returns an owner's unspent pool.

Param

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/budgets.PoolOf()"

Result