49 lines
5.2 KiB
JSON
49 lines
5.2 KiB
JSON
|
|
{
|
||
|
|
"contractName": "Subscription",
|
||
|
|
"constructorInputs": [
|
||
|
|
{ "name": "buyerPkh", "type": "bytes20" },
|
||
|
|
{ "name": "hostLock", "type": "bytes" },
|
||
|
|
{ "name": "priceSats", "type": "int" },
|
||
|
|
{ "name": "periodBlocks", "type": "int" },
|
||
|
|
{ "name": "maxFeeSats", "type": "int" }
|
||
|
|
],
|
||
|
|
"abi": [
|
||
|
|
{ "name": "pull", "inputs": [] },
|
||
|
|
{
|
||
|
|
"name": "cancel",
|
||
|
|
"inputs": [
|
||
|
|
{ "name": "pk", "type": "pubkey" },
|
||
|
|
{ "name": "s", "type": "sig" }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"bytecode": "OP_5 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_3 OP_ROLL OP_CHECKSEQUENCEVERIFY OP_DROP OP_TXINPUTCOUNT OP_1 OP_NUMEQUALVERIFY OP_0 OP_UTXOVALUE OP_0 OP_OUTPUTBYTECODE OP_3 OP_ROLL OP_EQUALVERIFY OP_0 OP_OUTPUTVALUE OP_3 OP_PICK OP_GREATERTHANOREQUAL OP_VERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_ROT OP_SUB OP_ROT OP_SUB OP_DUP 2202 OP_GREATERTHANOREQUAL OP_IF OP_1 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTVALUE OP_OVER OP_GREATERTHANOREQUAL OP_VERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_ENDIF OP_2DROP OP_DROP OP_1 OP_ELSE OP_5 OP_ROLL OP_1 OP_NUMEQUALVERIFY OP_5 OP_PICK OP_HASH160 OP_EQUALVERIFY OP_2ROT OP_CHECKSIGVERIFY OP_2DROP OP_2DROP OP_1 OP_ENDIF",
|
||
|
|
"source": "pragma cashscript ^0.13.0;\n\n// Subscription — a prepaid balance the host can draw from once per period,\n// and the buyer can take back at any time.\n// (Argus/src/lib/plans.js SUBSCRIPTION_ROADMAP; ROADMAP-MAINNET.md §9 step 4.)\n//\n// STATUS: chipnet draft. NOT REVIEWED.\n//\n// The buyer funds this script. Three things then hold, and the buyer can check\n// each from the script alone:\n//\n// · the balance stays theirs — cancel() needs only their signature, no\n// notice, no cooperation, and returns whatever is left;\n// · the host cannot take more than one period's price per period — pull()\n// pays exactly the host's lock at least `priceSats`, sends the rest back to\n// this same script, and can only run on an output that is `periodBlocks`\n// old, which the re-created output is not;\n// · nobody else gains anything — pull() needs no signature, so the host does\n// not have to be online with a key, but its only possible beneficiary is\n// the host's lock.\n//\n// A pull spends this input ALONE. With two inputs, one \"price to the host\"\n// output and one \"rest back to the script\" output could satisfy both, and the\n// host would collect two balances for one payment. One input means the fee\n// comes out of the balance too, bounded by `maxFeeSats`.\n//\n// The first period is not special-cased: the balance is drawn one period\n// after it is funded. A host that wants payment up front takes the first\n// period in the funding transaction itself.\ncontract Subscription(bytes20 buyerPkh, bytes hostLock, int priceSats, int periodBlocks, int maxFeeSats) {\n // One period's payment to the host.\n function pull() {\n require(this.age >= periodBlocks);\n require(tx.inputs.length == 1);\n\n int balance = tx.inputs[0].value;\n require(tx.outputs[0].lockingBytecode == hostLock);\n require(tx.outputs[0].value >= priceSats);\n require(tx.outputs[0].tokenCategory == 0x);\n\n // Everything else stays in the subscription, less a bounded fee. When\n // what would remain is too small to be an output, it is the fee.\n int rest = balance - priceSats - maxFeeSats;\n if (rest >= 546) {\n require(tx.outputs[1].lockingBytecode == tx.inputs[0].lockingBytecode);\n require(tx.outputs[1].value >= rest);\n require(tx.outputs[1].tokenCategory == 0x);\n }\n }\n\n // The buyer ends it and takes the balance. No conditions on where it goes.\n function cancel(pubkey pk, sig s) {\n require(hash160(pk) == buyerPkh);\n require(checkSig(s, pk));\n }\n}\n",
|
||
|
|
"fingerprint": "ed3b45444d0d4a41357fcd312e039baf769a8bc2e8a2d66c19624cae5078f046",
|
||
|
|
"debug": {
|
||
|
|
"bytecode": "5579009c63537ab275c3519d00c600cd537a8800cc5379a26900d100887b947b9476022202a26351cd00c78851cc78a26951d10088686d755167557a519d5579a98871ad6d6d5168",
|
||
|
|
"sourceMap": "32:4:49:5;;;;;33:28:33:40;;:8::42:1;;34:16:34:32:0;:36::37;:8::39:1;36:32:36:33:0;:22::40:1;37:27:37:28:0;:16::45:1;:49::57:0;;:8::59:1;38:27:38:28:0;:16::35:1;:39::48:0;;:16:::1;:8::50;39:27:39:28:0;:16::43:1;:47::49:0;:8::51:1;43:29:43:38:0;:19:::1;:41::51:0;:19:::1;44:12:44:16:0;:20::23;:12:::1;:25:48:9:0;45:31:45:32;:20::49:1;:63::64:0;:53::81:1;:12::83;46:31:46:32:0;:20::39:1;:43::47:0;:20:::1;:12::49;47:31:47:32:0;:20::47:1;:51::53:0;:12::55:1;44:25:48:9;32:20:49:5;;;:4;52::55::0;;;;53:24:53:26;;:16::27:1;:8::41;54:25:54:30:0;:8::33:1;52:38:55:5;;;30:0:56:1",
|
||
|
|
"logs": [],
|
||
|
|
"requires": [
|
||
|
|
{ "ip": 12, "line": 33 },
|
||
|
|
{ "ip": 16, "line": 34 },
|
||
|
|
{ "ip": 23, "line": 37 },
|
||
|
|
{ "ip": 29, "line": 38 },
|
||
|
|
{ "ip": 33, "line": 39 },
|
||
|
|
{ "ip": 46, "line": 45 },
|
||
|
|
{ "ip": 51, "line": 46 },
|
||
|
|
{ "ip": 55, "line": 47 },
|
||
|
|
{ "ip": 68, "line": 53 },
|
||
|
|
{ "ip": 70, "line": 54 }
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"compiler": {
|
||
|
|
"name": "cashc",
|
||
|
|
"version": "0.13.3",
|
||
|
|
"options": {
|
||
|
|
"enforceFunctionParameterTypes": true,
|
||
|
|
"enforceLocktimeGuard": true
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"updatedAt": "2026-10-04T14:02:00.557Z"
|
||
|
|
}
|