deviant/contracts/DeviantStepDRA.cash
walerikus 518a3ce174 chore: initial project baseline — full Deviant codebase under version control
Brings the whole project into git (previously only the on-ramp feature and
a few parallel files were tracked). Includes: wallet core (src/), CashScript
contracts/, the Capacitor shell (shells/), scripts/, tests, and the docs
corpus (wiki/, snapshots/, Parameters/, Archive/, KnowledgeBase text).

Excluded via .gitignore: node_modules/, dist/, .env (secrets), testnet WIF
key files (.chipnet-*.json, devWallets.ts), KnowledgeBase/RAW media (~9.6 GB),
transcripts/ (session logs), and machine-local config (.claude/*.local,
*.lock). Secret-scanned before commit — no credentials in the tree.

Note: src/swapMath.ts, src/swapBuilder.ts, contracts/OpenMintToken.cash are
legacy (OP_RETURN era) but still imported; committed as-is, flagged for a
separate removal once de-referenced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 20:38:07 +02:00

62 lines
3.1 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

pragma cashscript ^0.12.0;
// DeviantStepDRA — STEP/TIERED dynamic-rate asset (global bonding curve).
//
// Cousin of DeviantExpDRA (per-mint exponential) and DeviantBondingCurveFT
// (per-mint linear). Here the rate is held CONSTANT for `tierSize` mints (one
// "tier"), then escalates `rate * multiplier` at the tier boundary. This is the
// founder's step model: e.g. tierSize=100 ⇒ rate flat for 100 mints, then ×.
//
// Why this batches without pow: inside a tier every unit shares one rate, so a
// k-unit batch costs exactly `rate * k` — a single multiply, not a geometric
// sum. The boundary CAP (`k <= remainingInTier`) forbids a batch from crossing
// a tier, which keeps each batch single-rate (and so deliverable as one fungible
// bundle). Escalation is one multiply, only when a batch completes a tier — the
// carried-rate trick, so ANY rate law (incl. exponential-step) stays pow-free.
//
// Self-backed (ADR-0015): the delivered bundle locks `rate * k` sats for k units
// = `rate` per unit, redeemable at that mint-time rate. Pure dynamic-RATE asset.
//
// State: current per-unit rate lives in the reservoir's MUTABLE NFT commitment;
// mints-so-far is derived as `supply - reservoir`, mints-in-tier as `% tierSize`.
contract DeviantStepDRA(
bytes tokenCategory,
int multiplier, // rate x multiplier at each tier boundary (e.g. 2, 10)
int tierSize, // mints per tier before the rate escalates (e.g. 1, 100)
int supply // genesis FT supply (to derive minted = supply - reservoir)
) {
function claimBatch(int k, bytes recipientLockingBytecode) {
int rate = int(tx.inputs[this.activeInputIndex].nftCommitment); // current per-unit rate
require(rate > 0);
int reservoir = tx.inputs[this.activeInputIndex].tokenAmount;
require(k >= 1);
require(reservoir >= k);
// Boundary cap: a batch may not cross a tier boundary. At 95/100 minted
// with tierSize 100, remainingInTier = 5 ⇒ max 5 this tx (your scenario).
int minted = supply - reservoir;
int mintedInTier = minted % tierSize;
int remainingInTier = tierSize - mintedInTier;
require(k <= remainingInTier);
// [0] reservoir back to THIS contract: FT-k, value preserved, NFT mutable.
require(tx.outputs[0].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode);
require(tx.outputs[0].tokenCategory == tx.inputs[this.activeInputIndex].tokenCategory);
require(tx.outputs[0].tokenAmount == reservoir - k);
require(tx.outputs[0].value >= 546);
// Escalate the committed rate ONLY when this batch completes the tier.
if (k == remainingInTier) {
require(tx.outputs[0].nftCommitment == bytes(rate * multiplier));
} else {
require(tx.outputs[0].nftCommitment == bytes(rate));
}
// [1] k units to the claimer as ONE fungible bundle, each backed at `rate`.
require(tx.outputs[1].lockingBytecode == recipientLockingBytecode);
require(tx.outputs[1].tokenCategory == tokenCategory);
require(tx.outputs[1].tokenAmount == k);
require(tx.outputs[1].value == rate * k);
}
}