Your contract expires. You just don't know when.

Soroban state runs on a timer measured in ledgers, about five seconds each, and nothing tells you it is running out.

Open dashboard The code on GitHub

The thesis

One entry. Every contract built from that Wasm. They fail together.

Soroban keeps a contract's compiled code in a ledger entry of its own, and every contract deployed from that same code points at that one entry. So a contract's own state can be healthy until December while the code it runs expires in October — and without its code a contract cannot execute at all.

The real expiry is therefore the earliest entry, which is rarely the obvious one, and it is shared by every contract built from the same Wasm. That is the failure this exists to catch: a fleet of contracts reported healthy right up until they stop together.

See it on our three contracts

of the rent

98%

is that one shared code entry — 8,116,648 of 8,264,289 stroops, across all four of guinea-pig A's entries. Scanning only its instance and code, the same entry is 99%: identical rent, different denominator. The scope travels with the number.

What the tool actually prints

The honest parts are the persuasive parts

A real scan of guinea-pig A. It reports what it read, says that a single-contract scan cannot settle whether the code entry is shared, and says that storage it was not given keys for is unread.

Captured on 2026-09-12 and committed at docs/evidence/2026-09-12-w2-review/scan-a-human.txt. Its ledger numbers are from that day; the dashboard reads the chain now.

Coverage: known keys only — contract storage has NOT been fully enumerated. CANZNTAW7DYMCZ6EAY5BP672H4AL2O2HVRBP4O4HRUEZRATHQRRLXL6L: 0 explicit data key(s) No data keys were supplied, so any further entries are unread. A clean result covers only what was asked for, never the whole contract. HEALTHY instance AAAABgAAAA… contracts: CANZNTAW7DYMCZ6EAY5BP672H4AL2O2HVRBP4O4HRUEZRATHQRRLXL6L remaining: 1,400,453 ledgers — live ends at: ledger 6,025,589 approx: 2026-12-01T18:58:52.518Z (estimate — ledgers are the truth) observed: ledger 4,625,136 health: HEALTHY — Above threshold. HEALTHY code AAAAB8flXw… contracts: CANZNTAW7DYMCZ6EAY5BP672H4AL2O2HVRBP4O4HRUEZRATHQRRLXL6L ⚠ sharing: code entries are shared by every contract built from the same Wasm. This scan saw 1. Whether others depend on this entry cannot be determined from a single-contract scan — pass them together. remaining: 665,693 ledgers — live ends at: ledger 5,290,829 approx: 2026-10-20T06:28:52.518Z (estimate — ledgers are the truth) observed: ledger 4,625,136 health: HEALTHY — Above threshold. ! sharing-undetermined: Code entries are shared by every contract built from the same Wasm. This scan saw 1. Whether others depend on this entry cannot be determined from a single-contract scan — pass them together to see the real blast radius. contracts: CANZNTAW7DYMCZ6EAY5BP672H4AL2O2HVRBP4O4HRUEZRATHQRRLXL6L ! coverage-limited: No data keys were supplied, so any further entries are unread. A clean result covers only what was asked for, never the whole contract. contracts: CANZNTAW7DYMCZ6EAY5BP672H4AL2O2HVRBP4O4HRUEZRATHQRRLXL6L Worst entry health: HEALTHY (threshold 17,280 ledgers) Scan is PARTIAL — 2 issue(s). Absence is not health.

What it is for

One of ours expired, and we watched it happen.

Guinea-pig B was calibrated once on 5 September and then left alone — no extension, no watch, nothing keeping it alive. It declined on schedule and its instance entry is archived. Its timeline stays up after the event, because a record of what happened is evidence and not a status display.

The recorded decay, dot by dot

guinea-pig B · instance

expired

on
21 September 2026
at ledger
4,793,687

The four kinds of entry

Three are recoverable. One is not.

The shared code entry above is one of four kinds, and they do not end the same way. Which kind an entry is decides whether running out is a bill or a burial.

instance

The contract's own state pointer.

archived

code

The compiled Wasm. Every contract built from it shares this one entry.

archived

persistent

Durable stored values.

archived

temporary

Disposable stored values. Gone permanently, with no restore.

deleted

Read from the network's own configuration: a temporary entry's minimum is 720 ledgers, about an hour. Our own temporary entry had 688 left when it was first sampled.

How it works

Scan, watch, extend

Scan

Read a contract's entries through Soroban RPC: what remains, what expires first, what it costs to keep alive, and whether the code entry is shared — or whether that cannot be determined.

Watch

A scheduled job re-reads the entries you configure and alerts before they cross the thresholds: seven days for a warning, one day to act.

Extend

Evergreen has no authority over your contract. Extending a TTL needs no permission from anyone — it is a property of the chain, not a promise from us. It can pay rent, and nothing else.

Ready to safeguard your Soroban contracts?

Open the dashboard, run the CLI against any contract, or read the evidence we recorded doing it. Stellar testnet, read-only, no key and no account.

npx @evergreen-stellar/cli@0.1.1 scan <contract-id>

Open dashboard View on GitHub