Planet

[ developer docs · TON testnet PoC · unaudited ]

Architecture & interfaces

v1.7 · October 2026 · everything below is the deployed testnet reality, not a plan

1. Stack · 2. Live contracts · 3. The oracle flow · 4. Token, mint & redeem · 5. The fund · 6. Governance · 7. Public API · 8. Run it yourself · 9. Verification checklist · 10. Security

1. Stack

   off-chain                       on-chain (TON, Tolk)
   ─────────                       ─────────────────────
   Yahoo + Sina  ──► relayer ──►   PlanetCore ──► JettonMinter (PLT)
   (median, signed ed25519)        │  index, basket, fees, limits
                                   ├──► PlanetBasket (composition registry)
                                   ├──► PlanetBond   (stable-bond ledger)
                                   ├──► PlanetFund   (tokenised fund: NAV, subscribe/redeem)
                                   └──► PlanetGov    (PLTG staking, dividends, voting)
                                          ▲
                                       PlanetTimelock (delayed owner actions)

The core is deliberately small: it holds the basket, verifies signed prices, computes the index, and accounts fees. Everything that does not need to be atomic with that lives in a separate contract. Every privileged action is owner-gated, and the owner can be migrated to a timelock (§6) so changes are proposed, delayed, then executed.

2. Live contracts (TON testnet)

Testnet only. These tokens have no value; nothing is listed anywhere.

PlanetCorekQBUIDOcKIQZS_AMXjOL3usH69c3HIo0YudLoo_49eE0X2NJ
PLT minterkQC6zZ83qploNLCy0MdUNhKkBD9Tx25N-xWF7iDHkd3IJ2k3
PLTG minterkQDF0ixGco8WW4fqPB3XNdrNJ8vikFNkkyzKbz8hNJiFZ7OD
PlanetGovkQAK5XcQdykCOrA2-uFraTxq9CFD1NNdK5W4QrwCexNcBYJ3
Core owner timelock (60s)kQC_j4CrhPvbAX19_4C-PAoGNWBsaxj4GN5v6mIhGb7ctxQ1
Fund owner timelock (older, separate)kQBo0345y-RGi49-7WWaWAHyyNtiWe-JrT44iO3G9Cyom6YK

Open any address in a TON testnet explorer (e.g. tonviewer) and call the get-methods yourself — see §9.

3. The oracle flow

Planet does not depend on a third-party oracle network. Instead it accepts a signed price and verifies the signature on-chain, which means "connecting a real data source" reduces to publishing a public key.

  1. The relayer builds a payload {index, price, volatility, liquidity, riskState, timestamp}.
  2. It signs hash(domain_tag ‖ core_address ‖ payload) with its ed25519 key — the domain tag and contract address prevent replaying the payload on another deployment.
  3. SignedPriceUpdate (or SignedPriceUpdateN for M>2) carries the signature(s) and payload; anyone may relay it — authenticity comes from the signature, not from the sender.
  4. The core checks: enough distinct registered signers, strictly increasing timestamp, index in range, basket weights sum to 100%, and the price-jump guard.
  5. It recomputes the index over the active basket and stores the new value.

Registration is two owner messages: SetSigner{index, key} and SetThreshold{m}. A registered CAM adapter address can push instead (SetCam + CamUpdate).

4. Token, mint & redeem

PLT is a standard TEP-74 jetton; the minter's supply is the source of truth, and the core keeps a mirror for accounting.

Fees are band-based (0.5% near the index, 1% at 3–5% off, 2% beyond, plus a below-peg redemption penalty) and split 30% burn / 40% reserve / 20% staking / 10% risk fund.

5. The fund

PlanetFund is the "real product" shape: subscribers deposit, a custodian set confirms the purchase at the attested NAV (M-of-N, and shares are minted only on that confirmation — never on a deposit alone), and redemption is two-phase. Redemption is trustless about the shares: the subscriber transfers PLT into the fund's own jetton wallet, the transfer notification must come from that wallet (ERR_NOT_FUND_WALLET), the shares are burned, and only then can the custodian confirm the payout (ERR_NOT_FUNDED). Shares that never left the subscriber cannot be paid out.

6. Governance

7. Public API

GET /api/v1/statusLive index + full basket + accounting as JSON. Versioned path, ETag + 304, one error envelope, 503+Retry-After when the RPC is rate-limited.
GET /api/v1/oracleIs the price feed alive and sane? The age of the last push against the 6-hour limit, the signer set and threshold, whether base prices are locked, and — with ?full=1 — the weights check plus frozen/caution commodities and the signer keys. Cheap by default so a monitor can poll it. 503 means "could not read the chain", never a false "healthy".
GET /openapi.jsonThe OpenAPI 3.1 contract — generate a client from it instead of hand-parsing.
/api/statusDeprecated alias; replies 308 with Deprecation / Sunset / Link headers.

The API is read-only by design. There is no endpoint that signs or submits a transaction for you: minting and redeeming happen on-chain, signed by the user's own wallet. A custodial write API would be a funds-risk liability, so it does not exist.

8. Run it yourself

repo layout
  ton/            Tolk contracts + tests (Acton toolchain; builds in CI)
    contracts/    planet_core, planet_fund, planet_gov, planet_timelock, jetton/*
    scripts/      deploy + migration scripts
  relayer/        the off-chain price relayer (node, no third-party oracle)
  web/            this site + /dashboard + /faq + /docs + the v1 API
  app-tg/         the Telegram Mini App (Vite + React + TON Connect)

9. Verification checklist

  1. Call ppi(), assetCount(), assetAt(i), baseLocked(), lastOracleUpdate() on PlanetCore.
  2. Check the weights in assetAt(i) sum to exactly 1000000 and no weight exceeds 150000 (call maxAssetWeight()).
  3. Recompute the index from assetAt(i) with the formula in methodology §5 and compare to ppi().
  4. Compare lastOracleUpdate() against the wall clock — it should be minutes, never days, old.
  5. Confirm owner() is the timelock, not a plain wallet.
  6. Fetch /api/v1/status and confirm the numbers match your own contract reads.

10. Security & disclosure