[ public rulebook · TON testnet PoC · not a stablecoin ]
Basket & index methodology
version 1.0 · reviewed October 2026 · this page is the rulebook, not marketing
Why this page exists: a self-assembled commodity index is only as credible as its rulebook. If the basket were an undisclosed average of coin prices, the number would mean nothing. Everything below is the actual rule the contract enforces today (testnet), plus what is explicitly not claimed.
1. What the index is, and what it is not
The purchasing-power index (PPI) is a single number that tracks the price of a fixed basket of commodities, where 1.000000 is the index value on the base date. It is a measurement, computed on-chain from signed prices.
It is not a claim on any commodity, not redeemable for anything, and not backed by a reserve. There is no peg and no target. PLT is a synthetic token that expresses the index; it is not a stablecoin and this is not a yield product.
2. Composition
The live basket holds 14 commodities across four sectors. Each is a liquid, publicly quoted instrument with an independent second source where available.
| # | commodity | ref | weight | sector |
|---|---|---|---|---|
| 0 | WTI crude | CL=F | 14% | energy |
| 1 | Brent crude | BZ=F | 11% | energy |
| 2 | natural gas | NG=F | 8% | energy |
| 3 | gold | GC=F | 12% | metals |
| 4 | silver | SI=F | 7% | metals |
| 5 | copper | HG=F | 6% | metals |
| 6 | wheat | ZW=F | 9% | agriculture |
| 7 | corn | ZC=F | 7% | agriculture |
| 8 | soybean | ZS=F | 6% | agriculture |
| 9 | coffee | KC=F | 4% | agriculture |
| 10 | lumber (ETF) | WOOD | 4% | industrial |
| 11 | lithium (ETF) | LIT | 3% | industrial |
| 12 | water (ETF) | PHO | 5% | industrial |
| 13 | carbon (ETF) | KRBN | 4% | industrial |
Weights are stored on-chain in parts-per-million (1e6 = 100%). Source of truth:
relayer/assets.example.json in the repository.
3. The two rules that make it trustworthy
- Cap: no single commodity may exceed 15% (150 000 ppm). The contract rejects any add or re-weight above the cap, so no single market can dominate the index.
- Sum: the weights of the active basket must equal exactly 100%. The oracle path verifies this on every update, so the index cannot be silently diluted.
4. Base prices are frozen
Each commodity has a base price recorded when the basket is configured. Once the basket is locked, base prices are immutable: the governance actions that change weights cannot touch them. This is deliberate — if base prices were editable, the owner could rewrite the index history.
5. The index formula
Over all active commodities:
PPI = Σ ( wᵢ · Pᵢ / Pᵦᵢ ) ÷ Σ wᵢ
wᵢ— the commodity's weight (ppm)Pᵢ— its latest accepted pricePᵦᵢ— its base price
With nothing frozen this is the plain weighted average of the price ratios. When a commodity is frozen (see §7) it is dropped from both sums, and the remaining weights are renormalised — so a single bad data source cannot pull the whole index. All arithmetic is 1e6 fixed point; there are no floats anywhere on-chain.
6. Where prices come from
An off-chain relayer fetches each commodity from two independent sources where one exists (for example a Yahoo Finance futures quote and a Sina quote), converts both to the same unit, and takes the median. It signs the resulting payload with an ed25519 key and submits it to the contract, which verifies the signature on-chain before any state changes.
7. Validation gates
| gate | rule | effect |
|---|---|---|
| source divergence | two sources differ by > 2% | commodity marked frozen, excluded from the index |
| single-update jump | an update moves a price by > 50% | rejected outright |
| signature set | M-of-N distinct registered signers (currently 1 on testnet) | unsigned / under-signed updates rejected |
| domain separation | signature covers a tag + the contract address | a payload cannot be replayed on another deployment |
| timestamp | strictly increasing | replays rejected |
| staleness (mint) | index older than 6 hours | minting is refused — the protocol never prices off a stale oracle |
8. Update cadence
A scheduled run refreshes the feed once a day and pushes a commodity only when its price has moved more than 0.1% since the last on-chain value. The divergence trigger keeps the cost low without trading away freshness. The on-chain index is recomputed on every price update, and minting is refused against prices older than the six-hour staleness guard.
9. How the basket changes
Governance has exactly three moves, and nothing else:
- Add a commodity — appended at the next index; existing indices are never overwritten.
- Re-weight an existing commodity — subject to the 15% cap. Base prices are untouched.
- Retire a commodity — set its weight to 0. It stops contributing to the index without reordering anything (reordering is the dangerous operation this design avoids).
Because zeroing one weight breaks the 100% sum, a retirement must be paired with offsetting increases in the same batch; until the sum is restored, oracle updates fail loudly rather than producing a wrong index. On testnet the owner is a 60-second timelock, so every change is proposed, waits, then executes; production would use a multisig behind a longer delay, and the intent is a quarterly, rules-based re-weight.
10. What is explicitly not claimed
- No reserve, no collateral ratio, no redemption for commodities or dollars.
- No NAV, no yield, no peg and no promise to hold any particular value.
- No third-party audit yet — this is unaudited proof-of-concept code on testnet.
- No claim that the on-chain index equals any real tradable basket's return; it is a construction, and constructions have tracking differences.
11. Reproduce it yourself
Nothing here requires trusting this page. Read the chain directly:
ppi(),assetCount(),assetAt(i),baseLocked(),maxAssetWeight(),threshold()— the index and the basket.- /dashboard — the same values rendered live.
/api/v1/status— the same values as JSON, with the contract address and the last oracle timestamp.- The contract source and the basket file live in the public repository.
A copy of the index you compute from those values will match the on-chain number exactly, because the formula above is the only arithmetic involved.