deviant/contracts/TermCouponVault.cash
Local Dev debd6a6fbb chore: sweep in-flight work across all domains
Snapshot commit rolling up ~255 files of coherent-but-multi-domain in-flight
work that had accumulated on this branch. Split by area:

Contracts + covenants
- New: AsmFxSwap, DeviantOpenMintNBA, DeviantTieredMintOracleFT,
  TermCouponVault, UniformReserve, UniformReserveAggregate.
- Verify-artifact refresh (src/verify/artifacts/*.json + canonical.ts).

Wallet + shell (shells/app + src/wallet)
- App.tsx, MainScreen, ArtemisionScreen, AssetDetail, AgoraScreen,
  SettingsScreen, Unlock, TokenImportModal, UniformFiat/DepositPanel,
  KatalogosPanel (renamed from PinaxPanel), shell.css.
- src/wallet: wallet.ts, runtime.ts, index.ts. Core registry/chipnetFile.
- Deleted stale hook: useAllDevBalances.ts.

Cross-chain + correspondent (services/correspondent + scripts)
- Correspondent server/bch/config updates for PYUSD Solana, EURC Sepolia,
  aggregate reserve flows.
- New scripts: PYUSD roundtrip, EURC onboarding, GMX game loop /
  genesis / mint sanity, tiered mint fee, aggregate reserve, product2
  shares dividends, product3 t-bond, uniform fiat cell tests.

Telegram order-book (P2PExchange bot)
- db.ts, index.ts, en/ru locales — updates upstream from the extracted
  standalone repo at D:/Dev/P2PExchange.

Docs — Parameters (specs), wiki, snapshots, design mockups
- Parameters: FIATm/MBA_Shares/Potidaea/Anthemus refinements +
  ASM_CrossChain/DebitCredit + UniformFiat + Anthemus DEX MVP prompt +
  Artemision + Athenae Politeia + Philosophy + SSHkeyServer runbook +
  new dApp/{Artemision,Katalogos,Pinax,Pari_escrow,SURFACES}.
- wiki: cross-chain, games-tote, glossary, governance/voting-systems,
  infra, wallet, wallet-ui-design, decisions (ADR log).
- snapshots: catch-up entries and INDEX regeneration.
- design: mockups refreshed (agora, asset-detail, assets-tab, potidaea)
  + Potidaea assets + tote deploy notes.

Housekeeping
- .gitignore: exclude the new root test/session state files
  (.sol-vault-keys.json, .football-tote-state.json,
  .tote-platform-state.json, .redeem-roundtrip-state.json,
  .eurc-onboard-state.json — some contain oracle privkeys / vault
  secretKeyBase58; NEVER commit) + the .usdm-historical-chart.html
  chart output + MS Office `~$*` lock files + scripts/bundle-surfaces
  `build/` output. Also add scripts/bundle-surfaces.mjs.
- CLAUDE.md, WALLET-COORDINATION.md, snapshots/INDEX.md, design/README.md
  refreshed.
- package.json / package-lock.json bumps.

Verified: sensitive files at repo root confirmed ignored (git check-ignore
each). No `.env`, no raw WIF/xprv/mnemonic/secretKey/oraclePriv strings in
the staged diff. MS Word autosave file (`Parameters/Philosophy/~$*.docx`)
excluded and gitignored.

The WizardConnect responder work landed separately in the previous commit
(6987591); this is everything else that had accumulated alongside it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-07-29 01:14:33 +02:00

51 lines
2.7 KiB
Text

pragma cashscript ^0.12.0;
// TermCouponVault — ADR-0042 term-note / t-bond payout side.
//
// A bounded-term coupon vault. During the term the oracle attests coupon payouts
// (identical to DistributionVault.payout — replay-bound to the vault outpoint).
// The oracle simply stops attesting after maturity (off-chain term policy).
//
// The on-chain term mechanic is the MATURITY SWEEP: after `maturityTime` the issuer
// reclaims the unpaid coupon reserve. This uses CLTV correctly — a LOWER bound
// (`tx.time >= maturityTime`); "coupon only before T" is not directly enforceable
// on BCH (CLTV can't upper-bound), so the term end is expressed as "the reserve
// becomes reclaimable at maturity."
//
// The share's FLOOR (principal) is the self-backed share UTXO, redeemable anytime
// by a plain P2PKH spend — not gated here.
contract TermCouponVault(pubkey oraclePk, bytes sweepLockingBytecode, int maturityTime) {
// Coupon payout during the term (oracle-attested, replay-bound). 69-byte message:
// recipientLB(25) ‖ amount(8 LE) ‖ outpointTxHash(32) ‖ outpointIndex(4 LE).
function payout(bytes recipientLockingBytecode, datasig oracleSig, bytes oracleMessage) {
require(checkDataSig(oracleSig, oracleMessage, oraclePk));
require(oracleMessage.length == 69);
bytes lb, bytes r1 = oracleMessage.split(25);
bytes amtBytes, bytes r2 = r1.split(8);
bytes opTx, bytes opIdxBytes = r2.split(32);
require(lb == recipientLockingBytecode);
require(opTx == tx.inputs[this.activeInputIndex].outpointTransactionHash);
require(int(opIdxBytes) == tx.inputs[this.activeInputIndex].outpointIndex);
int amount = int(amtBytes);
require(amount >= 546);
require(tx.outputs[0].lockingBytecode == recipientLockingBytecode);
require(tx.outputs[0].value == amount);
require(tx.outputs[0].tokenCategory == 0x);
int remainder = tx.inputs[this.activeInputIndex].value - amount;
require(remainder >= 546);
require(tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode);
require(tx.outputs[1].value == remainder);
require(tx.outputs[1].tokenCategory == 0x);
}
// Maturity sweep — after the term, the issuer reclaims the unpaid reserve.
// CLTV lower bound: only valid once tx.time (locktime) >= maturityTime.
// Miner fee is funded by an external input; the full vault value goes to sweepLB.
function sweep() {
require(tx.time >= maturityTime);
require(tx.outputs[0].lockingBytecode == sweepLockingBytecode);
require(tx.outputs[0].value == tx.inputs[this.activeInputIndex].value);
require(tx.outputs[0].tokenCategory == 0x);
}
}