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>
61 lines
2.9 KiB
Text
61 lines
2.9 KiB
Text
pragma cashscript ^0.12.0;
|
|
|
|
// DistributionVault — ADR-0042 payout side.
|
|
//
|
|
// Holds the accrued shareholder profit-share pool. Pays each holder their
|
|
// oracle-attested entitlement; the company cannot take or redirect it — the
|
|
// only valid spend pays an oracle-named recipient an oracle-named amount and
|
|
// returns the remainder to this same vault.
|
|
//
|
|
// Replay-soundness: the oracle signature is bound to THIS vault UTXO's outpoint
|
|
// (txhash+index). Spending the UTXO consumes that outpoint and produces a new
|
|
// vault UTXO with a different outpoint, so a signature can be used at most once.
|
|
// Payouts are therefore sequential — one recipient per tx, each consuming the
|
|
// current vault UTXO and re-emitting the decremented pool.
|
|
//
|
|
// oracleMessage layout (69 bytes):
|
|
// recipientLockingBytecode(25) ‖ amount(8 LE) ‖ outpointTxHash(32) ‖ outpointIndex(4 LE)
|
|
//
|
|
// Output layout (payout):
|
|
// [0] recipient gets `amount` (pure BCH)
|
|
// [1] remainder back to this vault: value == vaultInput.value - amount
|
|
// [2+] miner-fee funding change (external input + change, unconstrained)
|
|
//
|
|
// Double-claim across recipients is the oracle's off-chain bookkeeping
|
|
// (it won't attest the same holder twice per epoch), bounded by the pool:
|
|
// the vault can never pay out more BCH than it holds.
|
|
|
|
contract DistributionVault(pubkey oraclePk) {
|
|
function payout(bytes recipientLockingBytecode, datasig oracleSig, bytes oracleMessage) {
|
|
require(checkDataSig(oracleSig, oracleMessage, oraclePk));
|
|
require(oracleMessage.length == 69);
|
|
|
|
// parse: recipient(25) ‖ amount(8) ‖ opTx(32) ‖ opIdx(4)
|
|
bytes lb, bytes r1 = oracleMessage.split(25);
|
|
bytes amtBytes, bytes r2 = r1.split(8);
|
|
bytes opTx, bytes opIdxBytes = r2.split(32);
|
|
|
|
require(lb == recipientLockingBytecode);
|
|
|
|
// bind this signature to THIS vault UTXO — prevents replay.
|
|
require(opTx == tx.inputs[this.activeInputIndex].outpointTransactionHash);
|
|
require(int(opIdxBytes) == tx.inputs[this.activeInputIndex].outpointIndex);
|
|
|
|
int amount = int(amtBytes);
|
|
require(amount >= 546);
|
|
|
|
// [0] pay the oracle-named recipient exactly the oracle-named amount.
|
|
require(tx.outputs[0].lockingBytecode == recipientLockingBytecode);
|
|
require(tx.outputs[0].value == amount);
|
|
require(tx.outputs[0].tokenCategory == 0x);
|
|
|
|
// [1] remainder back to this same vault — pool decrements by exactly `amount`.
|
|
// (Miner fee is funded by an external input + change at [2+], so the vault
|
|
// accounting stays exact; the company never touches this stream.)
|
|
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);
|
|
}
|
|
}
|