OpenedAt
Ask AI
OpenedAt is the height a register was created.
Command
gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/assets.OpenedAt()"
Result
Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.
Package assets is a per-owner fixed-asset register whose ledger postings are DERIVED from state rather than asserted by a caller.
A general ledger takes a debit code, a credit code and an amount from whoever is posting. That is the right design for a ledger and it means gno.land/r/.../books structurally CANNOT know that an entry was a depreciation charge, or that the charge for that period had already been made. Nothing stops an owner from booking the same month twice, or from skipping one, and nothing in the book can tell afterwards.
This realm closes that gap for one class of entry. It holds each asset's depreciation schedule as state, computes the charge from the schedule and the chain height, and keeps a per-asset HIGH-WATER MARK of the periods already booked. The amount is never a parameter. A charge therefore cannot be double-booked (the mark does not move backwards) and cannot be skipped (the next call books the whole span, because charges telescope exactly).
The resulting claim is narrow and checkable by anyone, which is the point:
1bookedAmount(asset) == asset.schedule.AccumulatedAt(bookedThrough(asset))
and, across a whole register,
1sum of bookedAmount over assets == the credit balance of 1590
Both are exported as Invariant and CrossFoot and both are FREE reads, deliberately — see "Why Rederive is not owner-only" below.
15500 Depreciation expense (expense, debit-normal)
21590 Accumulated depreciation (asset, CONTRA — see below)
Every posting is debit 5500 / credit 1590 for an equal amount, so the accounting equation offsets at 0 = 0 on an empty register and after every charge. There is no OpenAccount entrypoint and the underlying book is created with a hard cap of two accounts, so the chart cannot grow.
The COST BASIS never reaches the book. Booking an asset's cost would force a credit leg, and the only honest candidates are a liability ("2000 Acquisition payable") or an equity plug ("3000 Contributed capital"). Both assert how the asset was funded, which this realm does not know and must not invent. The cost stays in register state, where it is visible as data rather than as an accounting claim.
1590 is kind ASSET, so journal treats it as debit-normal and Balance() returns Debits - Credits — which reads NEGATIVE for accumulated depreciation. That is arithmetically correct for a contra-asset and is confusing on first reading, so both figures are exported and each is named for what it is: AccumulatedCredit is the positive contra balance.
A period is periodBlocks chain heights long, anchored to the height the asset was placed in service. Period k closes at placedAt + k*periodBlocks, and a partial period in progress is not counted and is not lost.
Block height, not wall-clock time, because that is this portfolio's convention: payroll, budgets, reimbursements and subscriptions all carry a periodBlocks field, and height is monotone by construction where block time is validator-reported. p/depreciation's Daily/Monthly/Yearly constants are SECONDS and are therefore not used here; its arithmetic is unit-agnostic (Periods is an integer division), so this is a mismatch in that package's documentation rather than a divergence from its behaviour. It is recorded in DISCOVERY.md § 6 rather than silently worked around.
Retire performs the final booking for the periods completed up to the retirement height and only then stops the asset. The two are one transaction on purpose: retiring without booking would leave depreciation that was genuinely incurred permanently unbooked, and booking after retirement would need an exception to the "retired assets do not accrue" rule. Historical charges always stand — the depreciation really happened.
Disposal gain or loss is OUT OF SCOPE for v1, and the reason is structural: it needs the cost-basis account this realm deliberately does not open, plus a proceeds figure the realm cannot observe because it holds no funds.
r/books exposes Rederive as an owner-only crossing function, to contain the cost of a full re-walk. This realm diverges, deliberately: the derivation IS the product, and a claim only its owner can check is not a claim worth making. Rederive, Invariant and CrossFoot are all free reads, so any third party can verify a register from vm/qeval without the owner's key.
The bound above is what makes that affordable, and a bound is not a price. Measured under the pinned onyx toolchain at the register cap — 64 assets on MaxLife declining schedules, the worst case this realm can hold:
So the design choice is stated with its cost rather than only its reason. Render is an ordinary rich-page figure; Rederive at cap is two orders of magnitude above it, falls on the queried node rather than the caller, and is reachable with no key and no fee. Whether a given RPC's query gas ceiling admits it AT THE CAP is a property of that node and is not measured here — if it refuses, the third-party-verification claim above fails exactly at the bound it was designed around. Invariant is per-asset and cheap; CrossFoot walks the assets only, not the postings.
This realm imports p/journal and p/depreciation. Neither is deployed yet, so the order is p/journal, p/depreciation, then this realm.
OpenedAt is the height a register was created.
gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/assets.OpenedAt()"