argus/contracts/subscription.json

52 lines
6.5 KiB
JSON
Raw Normal View History

covenants: the subscription and the delivery escrow, on one shared base (draft) The roadmap asks for the covenant capability to be built once and used three times. covenant.js is the shared part: artifact to bytecode, redeem script and lock, signing a covenant input, an unlocking script for any function, and assembling a transaction around covenant inputs. The registry library now sits on it, and so do the two new contracts. Subscription: the buyer funds a balance. Anyone may send one period's price to the host once per period, the rest going back to the same script; the buyer may take the balance back at any time with only their signature. A draw spends its input alone, because with two inputs one payment and one return could satisfy both and the host would keep a balance. Delivery escrow: a payment that can be collected only by the transaction that mints the agreed certificate to the buyer and publishes the agreed registration, or refunded by the buyer after a wait. It forbids any other token in the transaction: resolvers accept an update from any token of a name's category, so a deliverer who minted a second one alongside the certificate could later rewrite the buyer's name. It also sits at a fixed input, so two payments cannot be collected against one certificate. Neither can see the registry: an escrow cannot know the name was taken between payment and delivery. The contract says so. Drafts, not reviewed. The tests run every path in the VM under the 2025 and 2026 rules and count that the VM itself refused the tampered ones.
2026-10-04 16:08:10 +02:00
{
"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_PICK OP_1 000001 OP_WITHIN OP_VERIFY OP_3 OP_ROLL OP_CHECKSEQUENCEVERIFY OP_DROP OP_TXINPUTCOUNT OP_1 OP_NUMEQUALVERIFY OP_TXOUTPUTCOUNT OP_2 OP_LESSTHANOREQUAL OP_VERIFY OP_0 OP_UTXOVALUE OP_0 OP_OUTPUTBYTECODE OP_3 OP_ROLL OP_EQUALVERIFY OP_0 OP_OUTPUTVALUE OP_3 OP_PICK OP_NUMEQUALVERIFY 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_ELSE OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUALVERIFY 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 it has at most two outputs: the\n// price to the host, exactly, and the rest back to this script. Whatever\n// the fee allowance does not use goes to the miner, not to whoever built\n// the transaction.\n//\n// ONE BALANCE, ONE OUTPUT. The once-per-period limit is a property of an\n// output, not of an address. A buyer who pays the same address twice has two\n// balances, and each can be drawn every period. To add funds: cancel and fund\n// again, in one transaction if you like.\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 // A relative lock is a 16-bit block count. Anything outside that range\n // would be read as something else entirely: only its low bits, a\n // number of seconds, or no lock at all.\n require(within(periodBlocks, 1, 65536));\n require(this.age >= periodBlocks);\n require(tx.inputs.length == 1);\n require(tx.outputs.length <= 2);\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 } else {\n // Nothing is returned, so there must be nothing else: the leftover\n // is the fee, not a second output for whoever built the draw.\n require(tx.outputs.length == 1);\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": "d5796aeddba44e7674c0caad36eb5c7ab658a0a4fe9c7ebf8701acb5cc8ba302",
covenants: the subscription and the delivery escrow, on one shared base (draft) The roadmap asks for the covenant capability to be built once and used three times. covenant.js is the shared part: artifact to bytecode, redeem script and lock, signing a covenant input, an unlocking script for any function, and assembling a transaction around covenant inputs. The registry library now sits on it, and so do the two new contracts. Subscription: the buyer funds a balance. Anyone may send one period's price to the host once per period, the rest going back to the same script; the buyer may take the balance back at any time with only their signature. A draw spends its input alone, because with two inputs one payment and one return could satisfy both and the host would keep a balance. Delivery escrow: a payment that can be collected only by the transaction that mints the agreed certificate to the buyer and publishes the agreed registration, or refunded by the buyer after a wait. It forbids any other token in the transaction: resolvers accept an update from any token of a name's category, so a deliverer who minted a second one alongside the certificate could later rewrite the buyer's name. It also sits at a fixed input, so two payments cannot be collected against one certificate. Neither can see the registry: an escrow cannot know the name was taken between payment and delivery. The contract says so. Drafts, not reviewed. The tests run every path in the VM under the 2025 and 2026 rules and count that the VM itself refused the tampered ones.
2026-10-04 16:08:10 +02:00
"debug": {
"bytecode": "5579009c6353795103000001a569537ab275c3519dc452a16900c600cd537a8800cc53799d00d100887b947b9476022202a26351cd00c78851cc78a26951d1008867c4519d686d755167557a519d5579a98871ad6d6d5168",
"sourceMap": "39:4:65:5;;;;;43:23:43:35;;:37::38;:40::45;:16::46:1;:8::48;44:28:44:40:0;;:8::42:1;;45:16:45:32:0;:36::37;:8::39:1;46:16:46:33:0;:37::38;:16:::1;:8::40;48:32:48:33:0;:22::40:1;49:27:49:28:0;:16::45:1;:49::57:0;;:8::59:1;50:27:50:28:0;:16::35:1;:39::48:0;;:8::50:1;51:27:51:28:0;:16::43:1;:47::49:0;:8::51:1;55:29:55:38:0;:19:::1;:41::51:0;:19:::1;56:12:56:16:0;:20::23;:12:::1;:25:60:9:0;57:31:57:32;:20::49:1;:63::64:0;:53::81:1;:12::83;58:31:58:32:0;:20::39:1;:43::47:0;:20:::1;:12::49;59:31:59:32:0;:20::47:1;:51::53:0;:12::55:1;60:15:64:9:0;63:20:63:37;:41::42;:12::44:1;60:15:64:9;39:20:65:5;;;:4;68::71::0;;;;69:24:69:26;;:16::27:1;:8::41;70:25:70:30:0;:8::33:1;68:38:71:5;;;37:0:72:1",
covenants: the subscription and the delivery escrow, on one shared base (draft) The roadmap asks for the covenant capability to be built once and used three times. covenant.js is the shared part: artifact to bytecode, redeem script and lock, signing a covenant input, an unlocking script for any function, and assembling a transaction around covenant inputs. The registry library now sits on it, and so do the two new contracts. Subscription: the buyer funds a balance. Anyone may send one period's price to the host once per period, the rest going back to the same script; the buyer may take the balance back at any time with only their signature. A draw spends its input alone, because with two inputs one payment and one return could satisfy both and the host would keep a balance. Delivery escrow: a payment that can be collected only by the transaction that mints the agreed certificate to the buyer and publishes the agreed registration, or refunded by the buyer after a wait. It forbids any other token in the transaction: resolvers accept an update from any token of a name's category, so a deliverer who minted a second one alongside the certificate could later rewrite the buyer's name. It also sits at a fixed input, so two payments cannot be collected against one certificate. Neither can see the registry: an escrow cannot know the name was taken between payment and delivery. The contract says so. Drafts, not reviewed. The tests run every path in the VM under the 2025 and 2026 rules and count that the VM itself refused the tampered ones.
2026-10-04 16:08:10 +02:00
"logs": [],
"requires": [
{ "ip": 15, "line": 43 },
{ "ip": 18, "line": 44 },
{ "ip": 22, "line": 45 },
{ "ip": 26, "line": 46 },
{ "ip": 33, "line": 49 },
{ "ip": 38, "line": 50 },
{ "ip": 42, "line": 51 },
{ "ip": 55, "line": 57 },
{ "ip": 60, "line": 58 },
{ "ip": 64, "line": 59 },
{ "ip": 68, "line": 63 },
{ "ip": 81, "line": 69 },
{ "ip": 83, "line": 70 }
covenants: the subscription and the delivery escrow, on one shared base (draft) The roadmap asks for the covenant capability to be built once and used three times. covenant.js is the shared part: artifact to bytecode, redeem script and lock, signing a covenant input, an unlocking script for any function, and assembling a transaction around covenant inputs. The registry library now sits on it, and so do the two new contracts. Subscription: the buyer funds a balance. Anyone may send one period's price to the host once per period, the rest going back to the same script; the buyer may take the balance back at any time with only their signature. A draw spends its input alone, because with two inputs one payment and one return could satisfy both and the host would keep a balance. Delivery escrow: a payment that can be collected only by the transaction that mints the agreed certificate to the buyer and publishes the agreed registration, or refunded by the buyer after a wait. It forbids any other token in the transaction: resolvers accept an update from any token of a name's category, so a deliverer who minted a second one alongside the certificate could later rewrite the buyer's name. It also sits at a fixed input, so two payments cannot be collected against one certificate. Neither can see the registry: an escrow cannot know the name was taken between payment and delivery. The contract says so. Drafts, not reviewed. The tests run every path in the VM under the 2025 and 2026 rules and count that the VM itself refused the tampered ones.
2026-10-04 16:08:10 +02:00
]
},
"compiler": {
"name": "cashc",
"version": "0.13.3",
"options": {
"enforceFunctionParameterTypes": true,
"enforceLocktimeGuard": true
}
},
"updatedAt": "2026-10-04T14:39:23.518Z"
covenants: the subscription and the delivery escrow, on one shared base (draft) The roadmap asks for the covenant capability to be built once and used three times. covenant.js is the shared part: artifact to bytecode, redeem script and lock, signing a covenant input, an unlocking script for any function, and assembling a transaction around covenant inputs. The registry library now sits on it, and so do the two new contracts. Subscription: the buyer funds a balance. Anyone may send one period's price to the host once per period, the rest going back to the same script; the buyer may take the balance back at any time with only their signature. A draw spends its input alone, because with two inputs one payment and one return could satisfy both and the host would keep a balance. Delivery escrow: a payment that can be collected only by the transaction that mints the agreed certificate to the buyer and publishes the agreed registration, or refunded by the buyer after a wait. It forbids any other token in the transaction: resolvers accept an update from any token of a name's category, so a deliverer who minted a second one alongside the certificate could later rewrite the buyer's name. It also sits at a fixed input, so two payments cannot be collected against one certificate. Neither can see the registry: an escrow cannot know the name was taken between payment and delivery. The contract says so. Drafts, not reviewed. The tests run every path in the VM under the 2025 and 2026 rules and count that the VM itself refused the tampered ones.
2026-10-04 16:08:10 +02:00
}