Cosmic Bull

statements

gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements on onyx-1 testnet

realmapplicationaccountinglive on onyx-1

Publish financial statements over a chart of accounts you do not own.

Reads the books without being able to change them, so the statement and the ledger stay independent of each other.

In detail curated

Publishes a classified balance sheet, a cumulative income statement and an abnormality census DERIVED from the caller's own chart of accounts in r/<ns>/books -- the section, the sign and every total are functions of each account's Kind and NONE is supplied by the publisher. Publish takes no owner parameter, so authorization is STRUCTURAL rather than a check: the owner is cur.Previous().Address() and there is no address for a caller to forge. A published statement is FROZEN figures, not a frozen chart, which is why Verify answers 'do the frozen figures still hold?' and not 'is the chart untouched?' -- measured live on onyx-1, it read true before a ledger move and false after. That assets equals claims is DELIBERATELY NOT offered as a check: over any chart the ledger can produce it is algebraically identical to debits-equal-credits, which books enforces on every post, so it is true of a chart whose every account is classified backwards -- the fifth instance of the vacuous-true class this project has caught. The census is a finding to read and never a verdict: it catches a misclassification crossing the debit/credit-normal boundary and CANNOT catch one staying on the same side, and a genuine contra account is legitimately abnormal-signed. No custody, no admin, no cross-owner aggregate beyond a count.

Use it

A realm holds state. Reading it is a free query; changing it is a transaction you sign yourself.

Read it — no key, no account, no GNOT

gnokey query vm/qeval \
  --data 'gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements.Height()' \
  --remote https://rpc.onyx.testnets.gno.land:443

Height is read-only, so this is a query rather than a transaction: it costs nothing, signs nothing and needs no funded account. Every exported function is listed under the API below; swap the name and the arguments to read any of the others.

Change its state

Every state change is a transaction you sign with your own key — this site never asks for one and holds none. You do not have to hand-write the transaction: gnoweb generates the exact gnokey maketx call command for any of this realm's 1 crossing function, with the argument names filled in.

Read the known limitations further down this page first. They record what was not verified on chain, which is usually the part that matters.

Import it from another realm

import "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements"

The path is the address: there is no package manager, nothing to add to a manifest and no version to pin, so the package you compile against is the one the chain runs. It differs per chain because the namespace in it is the deploying account's.

Deployments

onyx-1 testnet onyx-1

RenderedSourceCall builderState

chain-attested
Import pathgno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements
Namespaceg1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3
Deployed at height330,800
Deploy transactionfd543b5621b44614df0617bd8e5f02d878a2383da6de52de822fc9541742d21c look it up on the RPC
Deployerg1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3
Gas used65,994,317
Storagenot attested per package on this chain — see the limitations below
Files on chaingnomod.toml statements.gno
Deployed bytesstatements.gno — 49,691 bytes
sha25616b7637439266c866b64ae31c0e0afe7b7473c664c20ebda85d3609f0034af7f
Realm addressg18wg9cmhrj7sgzy4xzrf96a9s8zlthu8crfta05 derived, never confirmed against the realm

Do not take the hash above on trust. $download returns the bytes onyx-1 is actually running; this command fetches them and prints their digest, which should equal the one in the table:

curl -sS 'https://onyx.testnets.gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements$download&file=statements.gno' | shasum -a 256

Expected: 16b7637439266c866b64ae31c0e0afe7b7473c664c20ebda85d3609f0034af7f — 49,691 bytes. Use curl: the gno.land edges answer Python's default user-agent with HTTP 403.

API

chain-derived 21 exported functions.

Every function below deep-links to gnoweb's call builder, which generates a ready-to-run gnokey maketx call for it:

AbnormalAtAbnormalCountAbnormalInBalanceSheetCountCurrentAbnormalCountCurrentBalanceSheetCurrentIncomeStatementCurrentRowsHasHeightIncomeStatementLatestLedgerPublishPublishedAtRenderRowsSectionTotalTotalVerify

Overview

Package statements publishes classified financial statements over a chart of accounts this realm does not own, cannot write, and did not supply.

A PUBLISHED STATEMENT IS A CLAIM ABOUT A CLAIM

Read this before trusting any figure this realm returns, and read it before publishing anything here.

r/books says of itself, correctly: *"a book is a set of claims by its owner"*. It holds no asset, so nothing ties an account reading `Cash 5000` to 5000 real ugnot anywhere. A statement derived from such a book inherits that completely — and then **adds a layer of apparent authority**, because a balance sheet at a stable on-chain path, stamped with a height and a sequence number, looks like an audited artifact. It is a self-report of a self-report.

This realm performs no audit, verifies no event, and holds no custody. What it guarantees is narrow and exact: the figures below are **derived** from the owner's chart at a height, by code nobody can parameterise, and frozen. That the chart describes anything real is not claimed here and is not checkable from here.

Derived, not supplied — which is the whole reason this realm exists

Every figure comes from r/books through its own read surface. A publisher says *when to freeze*; they do not say what the statement says. The alternative design — the publisher passes the rows in — was considered in DISCOVERY.md § 4 and is fatal to the thesis: a statement whose inputs its publisher typed is an assertion about nothing, and this realm would be a pure function with a storage bill.

The consequence is that **this is the first first-party realm-to-realm import in this portfolio, and it is permanent.** Bytes are immutable after addpkg, so these statements read the r/books at BooksPath forever. If that realm ever gets a v2, published statements keep reading v1 — arguably correct for an auditable artifact, and still a coupling nothing here has carried before.

What is published and what is not

Publish freezes the three figures a balance sheet needs, the three an income statement needs, and the abnormality census. It does NOT freeze the chart: account names, codes and the postings behind them stay in r/books, which keeps writing them.

So Verify answers **"do the frozen figures still hold?"** and NOT **"is the chart untouched?"**. The two differ and the difference is demonstrable: a posting that moves 100 from one asset account to another leaves Assets, Claims, the net and the row count all identical, and Verify still reads true. It is a reconciliation, not a seal. The seal on the chart's own history is r/books' append-only journal, and that is where to look.

The income statement is cumulative since inception

p/journal's Close is a backdating seal: it refuses entries dated at or before a cutoff and sweeps no nominal account into equity. There is no retained-earnings account and no closing entry anywhere in the stack, so revenue and expense accumulate from the book's first posting forever.

Every accessor and every rendered line therefore carries the word cumulative. A reader who takes them for a period figure misreads every statement this realm publishes. A period statement needs entry-level data; see DISCOVERY.md § 6.8.

The balance sheet identity is NOT offered as a check

Assets and Claims are both reported. Their equality is not exposed as a verdict anywhere, because over a chart drawn from a p/journal Book it is algebraically identical to `totalDebits == totalCredits`, which r/books enforces on every post — a constant true, and true of a chart whose every account is classified backwards. p/statements' package doc carries the derivation. A `Balances()` here would be the fifth instance of the vacuous-true class this project keeps finding in its own work.

What ships instead is the census: AbnormalCount and AbnormalIn report every account whose balance runs against its kind. That survives a balanced book. Its incompleteness is exact and is stated at AbnormalCount.

NO CUSTODY — and refusing coins is not the same as not holding them

There is no coinio import, no payable path, no fee, no withdrawal, no admin. So Publish REFUSES a transaction carrying coins: a realm with no withdrawal path that silently accepts ugnot strands it permanently, and "we hold no funds" would then be true of the design and false of the balance.

No admin, and no cross-owner aggregate beyond a count

The deploying namespace has no privilege here: no setter, no pause, no ability to publish or to read anything a stranger cannot read. Total is a count of publications and nothing more. r/books refuses to enumerate books because such a total would sum every stranger's self-reported assertion; the same reasoning applies one level up, so there is no way to enumerate publishers and no cross-owner figure of any kind.

What this realm does NOT do

r/books: /r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/books p/journal: /p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/journal p/statements: /p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements

Imports

Constants and variables

BooksPath is the ledger realm every figure here is derived from.

It is taken BY VALUE from that realm's own exported constant rather than typed out again, so this is the compile-time pin itself and not a second copy of it that could drift. A reader checking which ledger a statement describes is reading the import, not a string in a doc comment.

const BooksPath = books.RealmPath

PublicationsAreUncapped records a decision by its absence, because every other realm in this portfolio caps its per-owner state and a reader will look for the cap here.

There is none, and the three reasons are:

A cap added only so a test could reach it would be worse than none.

const PublicationsAreUncapped = true

RealmPath is this realm's own path, used to build Render links.

const RealmPath = "/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements"

RenderAbnormalLimit caps how many census rows one Render call emits. A chart may hold books.MaxAccountsPerBook accounts and in a pathological book every one of them is abnormal.

const RenderAbnormalLimit = 25

RenderPublicationLimit caps how many of a publisher's statements one Render call lists. Publications are unbounded (see PublicationsAreUncapped), so this is what keeps a publisher's page cost flat.

const RenderPublicationLimit = 20

Functions

AbnormalAt

func AbnormalAt(owner address, seq int64, i int) (code, name, kind, section string, balance int64)

AbnormalAt returns one census row by its zero-based index. Rows are in ascending account-code order, which p/statements enforces as a precondition on its input rather than relying on this realm to sort.

section is the row's statement section, derived from its kind through the same mapping the totals were built from.

AbnormalCount

func AbnormalCount(owner address, seq int64) int

AbnormalCount is how many accounts in a frozen statement carry a balance running against their kind.

What the census catches, and what it cannot

This is the only partial answer in this portfolio to p/journal's consumer obligation 7 — a kind set wrongly when an account was opened is undetectable in that package and undetectable anywhere else in it. The answer is sound and incomplete, and the incompleteness is exact:

So a non-zero count is A FINDING TO READ, never a verdict, and a zero count is not a clean bill of health.

AbnormalIn

func AbnormalIn(owner address, seq int64, section string) int

AbnormalIn counts the abnormal accounts presented in one section: "assets", "claims" or "performance".

BalanceSheet

func BalanceSheet(owner address, seq int64) (assets, liabilities, equity, cumulativeNet, claims int64)

BalanceSheet returns a frozen statement's balance sheet.

cumulativeNet appears here as an EXPLICIT RECONCILING LINE because nothing in this stack closes a nominal account into equity. claims is liabilities + equity + cumulativeNet, so a reader who checks assets against liabilities + equity alone and finds it short by exactly cumulativeNet is not looking at a bug.

assets and claims are both returned and their equality is deliberately not offered as a verdict; see the package doc.

Count

func Count(owner address) int

Count is how many statements an owner has published. Zero for an address that has never published, which is not an error.

CurrentAbnormalCount

func CurrentAbnormalCount(owner address) int

CurrentAbnormalCount runs the census over the owner's chart now. Its reach is exactly AbnormalCount's.

CurrentBalanceSheet

func CurrentBalanceSheet(owner address) (assets, liabilities, equity, cumulativeNet, claims int64)

CurrentBalanceSheet derives the owner's balance sheet from their chart NOW, publishing nothing. It exists so that a false Verify is diagnosable: a reader can see which figure moved instead of only that one did.

Each of the three Current accessors re-reads the chart, so asking for all of them is three walks. Verify is the single-call form.

CurrentIncomeStatement

func CurrentIncomeStatement(owner address) (cumulativeRevenue, cumulativeExpenses, cumulativeNet int64)

CurrentIncomeStatement derives the owner's income statement from their chart now. Cumulative since inception; see the package doc.

CurrentRows

func CurrentRows(owner address) int

CurrentRows is how many accounts the owner's chart holds right now, as this realm reads it. It agrees with books.Accounts by construction — chartOf refuses when they disagree — and is exposed so a reader comparing a frozen statement's Rows against the live chart does not have to call two realms.

Has

func Has(owner address, seq int64) bool

Has reports whether a publication exists, so a reader can distinguish it from the panics every accessor below raises for an unknown one.

Height

func Height() int64

Height is the chain height this realm stamps publications with. Exposed so a caller can predict what Publish will record.

IncomeStatement

func IncomeStatement(owner address, seq int64) (cumulativeRevenue, cumulativeExpenses, cumulativeNet int64)

IncomeStatement returns a frozen statement's income statement. Every figure is CUMULATIVE SINCE THE BOOK'S FIRST POSTING, not a period figure; see the package doc.

Latest

func Latest(owner address) (int64, bool)

Latest is an owner's highest sequence number, and whether they have published at all. The second result matters: sequence numbers start at 1, so a zero first result means "never published" and never "statement 0".

Ledger

func Ledger() string

Ledger is the path of the realm every figure here is derived from. The constant is BooksPath; this is the accessor for a caller that cannot read a constant off a package.

Publish

func Publish(cur realm) int64

Crossing function. Callable from a transaction via MsgCall, and from another realm as Publish(cross(cur), ...).

Publish freezes the caller's own statement at the current height and returns its sequence number, which starts at 1 for each publisher.

The owner is cur.Previous().Address() and there is no owner parameter, so authorization is structural rather than a check: there is no address for a caller to forge and no way to publish a statement about somebody else's book. A realm that calls in publishes over its own book for free, which arrives as a property of that rule rather than as a feature — the same way it does in r/books.

An EMPTY CHART IS REFUSED, and this is a deliberate divergence from p/statements, whose doc calls zero rows "a legitimate statement of nothing". It is legitimate for a pure function and not worth a storage deposit here: a frozen row of zeros at a permanent path reads as a statement rather than as an absence, and the publisher has paid to say nothing.

Everything that can refuse does so before this realm writes anything.

PublishedAt

func PublishedAt(owner address, seq int64) int64

PublishedAt is the chain height a statement was frozen at.

Render

func Render(path string) string

Render serves the index at "", a publisher's page at "<address>", and one statement at "<address>/<seq>".

Every caller-supplied string — an account's code and name, both of them an owner's free text in r/books — goes through [cell]. Free text reaching Render unescaped is the one injection-shaped surface a realm with no custody still has, and here the bytes come from a THIRD realm's state, which does not make them safer.

Rows

func Rows(owner address, seq int64) int

Rows is how many accounts the statement classified.

SectionTotal

func SectionTotal(owner address, seq int64, section string) int64

SectionTotal returns the figure presented for one section: "assets", "claims" or "performance". The performance total is the income statement's bottom line, not the sum of its two components.

Total

func Total() int

Total is how many statements exist across every publisher. It is a count and nothing more; see the package doc on why there is no enumeration and no cross-owner figure.

Verify

func Verify(owner address, seq int64) bool

Verify re-derives the owner's chart now and reports whether every figure in a frozen statement still holds, including the census rows.

Read the ceiling before quoting this

A true result means THE FROZEN FIGURES STILL HOLD. It does NOT mean the chart is untouched, and the gap is demonstrable rather than theoretical: a posting that moves an amount between two asset accounts leaves Assets, Claims, the net, the row count and the census all identical, and this still reads true. The suite pins that case.

A false result is a real difference and nothing more: the owner has posted since, which is the normal life of a book. It is not evidence of misconduct, and this realm offers no mechanism that treats it as such.

What proves the chart's own history is r/books' append-only journal, where a wrong entry is corrected by a visible reversal rather than an edit.


Doc text is reproduced as vm/qdoc returns it. The node markdown-escapes doc comments, so a bracket or angle bracket may carry a backslash the committed source does not have. The source itself is at source and in this repository.

Dependencies

chain-attested
Importschain/runtime, chain/runtime/unsafe, gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/journal, gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements, gno.land/p/nt/avl/v0, gno.land/p/nt/markdown/sanitize/v0, gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/books, strconv, strings
First-party dependenciesgno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/journal, gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/statements, gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/books

Known limitations

Recorded by the people who built and deployed it. This list is deliberately not empty where honesty costs something.

curated

Source

Source fileonyx/r/statements/statements.gno at commit c2e10d17ffbf in the project repository (not public — the digest command above is the check that needs no repository)
Matches the deployed bytesyes — byte-identical