deviant/contracts/DeviantEscFeeBlockHeightV2.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

69 lines
3 KiB
Text

pragma cashscript ^0.12.0;
// DeviantEscFeeBlockHeightV2 — EXPERIMENTAL FEASIBILITY TEST (not production).
//
// Workaround for trigger 3 after DeviantEscFeeBlockHeight.cash failed to
// compile (tx.time is not a readable integer — only a require() operand).
//
// Approach: the claimer PASSES the block height as an argument
// (`claimedHeight`), and the contract binds it to consensus with
// require(tx.time >= claimedHeight);
// which lowers to OP_CHECKLOCKTIMEVERIFY: the tx's nLocktime must be
// >= claimedHeight, and CLTV guarantees nLocktime <= the real current
// height. So claimedHeight <= currentHeight. The fee is then computed
// from claimedHeight arithmetically (which IS allowed — it's a normal int).
//
// !!! SECURITY HOLE (the headline finding for trigger 3) !!!
// require(tx.time >= claimedHeight) only puts a LOWER bound on the height.
// Script has NO opcode to read the *actual* current height as a value, so
// it cannot force claimedHeight up to "now". A rational claimer therefore
// always passes the SMALLEST height that still validates (>= genesisHeight),
// paying the base fee forever. Block-height fee escalation is thus NOT
// adversarially enforceable on BCH — it degrades to "honest claimers pay
// more, cheaters pay base." Documented, not production-viable.
contract DeviantEscFeeBlockHeightV2(
bytes tokenCategory,
int backingRateSats,
int baseFeeBps,
int feeStepBps,
int maxFeeBps,
int genesisHeight,
int blocksPerStep,
bytes founderLockingBytecode
) {
function claim(int tokenAmount, bytes recipientLockingBytecode, int claimedHeight) {
require(tokenAmount > 0);
// Bind the claimed height to consensus (lower bound only — see hole above).
require(tx.time >= claimedHeight);
require(claimedHeight >= genesisHeight);
int currentReservoir = tx.inputs[this.activeInputIndex].tokenAmount;
int grossSats = tokenAmount * backingRateSats;
int elapsed = claimedHeight - genesisHeight;
int feeBps = baseFeeBps + (elapsed / blocksPerStep) * feeStepBps;
if (feeBps > maxFeeBps) {
feeBps = maxFeeBps;
}
int feeSats = grossSats * feeBps / 10000;
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 == currentReservoir - tokenAmount);
require(tx.outputs[0].value >= 546);
require(tx.outputs[1].lockingBytecode == recipientLockingBytecode);
require(tx.outputs[1].tokenCategory == tokenCategory);
require(tx.outputs[1].tokenAmount == tokenAmount);
require(tx.outputs[1].value == grossSats);
if (feeSats > 0) {
require(feeSats >= 546);
require(tx.outputs[2].lockingBytecode == founderLockingBytecode);
require(tx.outputs[2].value == feeSats);
require(tx.outputs[2].tokenCategory == 0x);
}
}
}