Skip to content

About

Soroban contracts for Plimsoll: on-chain reserve coverage for Stellar-issued assets. Reporter registry, coverage ledger, and an is_covered() gate other contracts can call.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Plimsoll

CI soroban-sdk 28 testnet Docs Apache-2.0 unaudited

Plimsoll contracts

Soroban contracts that answer one question about a Stellar-issued asset: how much of what is circulating is backed, according to whom, and how recently?

Circulating supply is computed from public ledger data and posted on-chain with a hash of its breakdown. Reserve figures are posted by the issuer's own account, a registered auditor, or a registered transcriber, and the signer sets the report's tier. Any contract can then call:

is_covered(asset, min_bps, max_age, min_tier) -> bool

and refuse an asset that is under-backed or whose figures are out of date.

Repo What it is
plimsoll-contracts (this repo) Rust/Soroban contracts
plimsoll-app Web app and TypeScript SDK
plimsoll-indexer Go service: supply poster, event indexer, read API

Live app: https://plimsoll-app-gths-amber.vercel.app/ (mirror: https://plimsoll-protocol.github.io/plimsoll-app/)
Docs: https://plimsoll-protocol.gitbook.io/plimsoll-protocol-docs/

Maintainers

Maintainer GitHub Contact
dunnidev @dunnidev GitHub Discussions

Questions, ideas and contributor coordination happen in Discussions.

Contracts

Contract Responsibility
reporter-registry Who may speak: auditors, transcribers and supply posters, managed by an admin.
coverage-ledger What was said: asset listings, supply snapshots, reserve reports, and the coverage / is_covered queries.
covered-vault Reference consumer: refuses deposits while the asset is not covered; never blocks withdrawals.
plimsoll-types Shared types, basis-point math and cross-contract client traits.
reporter-registry  ◀── role_of ──  coverage-ledger  ◀── is_covered ──  covered-vault
                                         │
                                         └── name() ──▶ Stellar Asset Contract

The full function-by-function specification is in docs/SPEC.md, and the event topic and data layouts every off-chain reader depends on are in docs/EVENTS.md.

Why it is Stellar-specific

  • Issued assets are a protocol feature. Supply for any classic asset can be summed from trustlines, claimable balances, liquidity pools and contract balances, with no cooperation from the issuer.
  • The issuer account can sign Soroban auth. A report signed by asset.issuer is unforgeable, which is what the Issuer-signed tier relies on.
  • Every asset has a built-in Stellar Asset Contract whose name() is CODE:ISSUER. list_asset accepts only genuine SACs and parses that name, so a look-alike token cannot be listed under a real issuer.

Tiers

Tier Value Who signs
Auditor-signed 3 Address registered with the Auditor role
Issuer-signed 2 The asset's issuer account
Transcribed 1 Address registered with the Transcriber role

Testnet deployment

Contract Address
reporter-registry CCZCBR7MGSW5LGIEUQR5TU5Z7JQWBDEESB3RGPTRPMCBUMOISRPY7GOB
coverage-ledger CC2QQ7R4FLPHZP7KA5AO4IASXXICTG6N4GQXCXITTEBNYQEYTYXKMN4D
covered-vault CC3SUECAJSAC4PBV4QLUII7X5Y4WNVL5YGTBAQ4CHCAH6R3QLRYJUZHQ

Listed demo assets: PUSD (demo issuer, SAC CCHPT4…HIM7S) and Circle's testnet USDC (SAC CBIELT…DAMA). Full record: deployments/testnet.json.

Quick start

Requirements: Rust stable with the wasm32v1-none target, and Stellar CLI 28 or later.

git clone https://github.com/plimsoll-protocol/plimsoll-contracts
cd plimsoll-contracts

cargo test                 # 58 tests across all crates
stellar contract build     # wasm in target/wasm32v1-none/release/

python3 scripts/check_wasm_sizes.py   # each wasm against its size budget

The size budgets live in size-budgets.json and CI enforces them, so a contract cannot quietly grow towards the install limit. Raising one is fine; doing it in the commit that needs the room is the point.

Deploy your own copy to testnet (creates and funds the identities it needs):

./scripts/deploy-testnet.sh

Query the live deployment:

stellar contract invoke --network testnet --send=no \
  --id CC2QQ7R4FLPHZP7KA5AO4IASXXICTG6N4GQXCXITTEBNYQEYTYXKMN4D -- \
  coverage --sac CCHPT4TEJDPZQDSUVW3NP6A35ROGV4WEFZKT45SKWYCFZSUB7R5HIM7S --min_tier 1

Keeping the demo honest

A reserve report expires. The PUSD vault asks for one at most 7 days old, so the demo needs its reserves restated or it quietly stops demonstrating anything — is_covered starts answering false for a well-backed asset, and both demo vaults refuse deposits for different reasons that look identical from outside.

./scripts/refresh-demo-reserves.sh verify   # does the demo still say what it claims?
./scripts/refresh-demo-reserves.sh post     # restate the reserves (needs the reporter keys)

verify needs no keys: it asks the contract whether PUSD is covered and QUSD is refused, and checks that every report's doc_hash still matches the document it points at. The Demo coverage workflow runs it twice a day and restates the reserves when they are more than three days old, which keeps the standing statements in docs/demo matching what is on chain.

Contributing

Issues labelled good first issue are scoped for a first pull request. Read CONTRIBUTING.md before you start, and comment on an issue to have it assigned.

Security reports: see SECURITY.md. Do not open public issues for vulnerabilities.

Contributors

Contributors

License

Apache-2.0

About

Soroban contracts for Plimsoll: on-chain reserve coverage for Stellar-issued assets. Reporter registry, coverage ledger, and an is_covered() gate other contracts can call.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages