59 lines
7.5 KiB
JSON
59 lines
7.5 KiB
JSON
|
|
{
|
||
|
|
"contractName": "DeliveryEscrow",
|
||
|
|
"constructorInputs": [
|
||
|
|
{ "name": "buyerPkh", "type": "bytes20" },
|
||
|
|
{ "name": "certLock", "type": "bytes" },
|
||
|
|
{ "name": "nameCommitment", "type": "bytes" },
|
||
|
|
{ "name": "payloadLock", "type": "bytes" },
|
||
|
|
{ "name": "beaconLock", "type": "bytes" },
|
||
|
|
{ "name": "beaconDust", "type": "int" },
|
||
|
|
{ "name": "refundAfter", "type": "int" }
|
||
|
|
],
|
||
|
|
"abi": [
|
||
|
|
{ "name": "deliver", "inputs": [] },
|
||
|
|
{
|
||
|
|
"name": "refund",
|
||
|
|
"inputs": [
|
||
|
|
{ "name": "pk", "type": "pubkey" },
|
||
|
|
{ "name": "s", "type": "sig" }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
],
|
||
|
|
"bytecode": "OP_7 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_INPUTINDEX OP_1 OP_NUMEQUALVERIFY OP_0 OP_OUTPOINTINDEX OP_0 OP_NUMEQUALVERIFY OP_0 OP_OUTPOINTTXHASH OP_0 OP_OUTPUTBYTECODE OP_3 OP_ROLL OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_ROT OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_NUMEQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_ROT OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_2 OP_OUTPUTBYTECODE OP_ROT OP_EQUALVERIFY OP_2 OP_OUTPUTVALUE OP_ROT OP_GREATERTHANOREQUAL OP_VERIFY OP_2 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_TXOUTPUTCOUNT OP_6 OP_LESSTHANOREQUAL OP_VERIFY OP_TXOUTPUTCOUNT OP_3 OP_GREATERTHAN OP_IF OP_3 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_ENDIF OP_TXOUTPUTCOUNT OP_4 OP_GREATERTHAN OP_IF OP_4 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_ENDIF OP_TXOUTPUTCOUNT OP_5 OP_GREATERTHAN OP_IF OP_5 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_ENDIF OP_2DROP OP_DROP OP_1 OP_ELSE OP_7 OP_ROLL OP_1 OP_NUMEQUALVERIFY OP_7 OP_PICK OP_HASH160 OP_EQUALVERIFY OP_7 OP_ROLL OP_7 OP_ROLL OP_CHECKSIGVERIFY OP_5 OP_ROLL OP_CHECKSEQUENCEVERIFY OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ENDIF",
|
||
|
|
"source": "pragma cashscript ^0.13.0;\n\n// DeliveryEscrow — payment for a name that can only be collected by the\n// transaction that registers it to the buyer.\n// (Decentralized.DNS/DESIGN-trustless-purchase.md §4.)\n//\n// STATUS: chipnet draft. NOT REVIEWED.\n//\n// A buyer who cannot build a registration themselves (pay-by-QR, any wallet)\n// pays this script instead of paying a registrar. The money then has exactly\n// two ways out:\n//\n// deliver() anyone may spend it — in a transaction that mints the agreed\n// certificate to the buyer and publishes the agreed registration.\n// \"Took the money and did not register\" is not a risk the buyer\n// has to weigh; it is a transaction that cannot be built.\n// refund() the buyer takes it back with their signature once it is\n// `refundAfter` blocks old.\n//\n// What deliver() pins down, output by output:\n// 0 the certificate — a NEW token category created by this transaction\n// (its id is input 0's outpoint), an NFT with no capability, commitment =\n// the name, no fungible amount, locked to the buyer's lock\n// 1 the registration payload, byte for byte as agreed (OP_RETURN)\n// 2 the discovery beacon, at least its dust\n// … and NO other output may carry a token. Without that, the deliverer could\n// mint a second, minting-capable token of the same category alongside the\n// certificate and later use it to update the buyer's name.\n//\n// The escrow must be input 1 (input 0 is the genesis outpoint). That makes it\n// one escrow per transaction: two payments for the same name could otherwise\n// both be collected against a single certificate.\n//\n// WHAT IT CANNOT PROMISE. Script sees this transaction, not the registry. If\n// the name was registered by someone else between payment and delivery, a\n// deliverer can still mint a certificate that satisfies every line here and\n// that no resolver will honour (\"first valid registration wins\" is a resolver\n// rule). The window is the buyer's to keep short: check the name is free, pay,\n// and refund if delivery does not come.\ncontract DeliveryEscrow(\n bytes20 buyerPkh,\n bytes certLock, // where the certificate must go (the buyer's token address, or their covenant)\n bytes nameCommitment, // the on-chain name, as the certificate's commitment\n bytes payloadLock, // the full OP_RETURN locking bytecode of the agreed REG payload\n bytes beaconLock,\n int beaconDust,\n int refundAfter\n) {\n function deliver() {\n require(this.activeInputIndex == 1);\n require(tx.inputs[0].outpointIndex == 0);\n bytes category = tx.inputs[0].outpointTransactionHash;\n\n require(tx.outputs[0].lockingBytecode == certLock);\n require(tx.outputs[0].tokenCategory == category);\n require(tx.outputs[0].nftCommitment == nameCommitment);\n require(tx.outputs[0].tokenAmount == 0);\n\n require(tx.outputs[1].lockingBytecode == payloadLock);\n require(tx.outputs[1].tokenCategory == 0x);\n\n require(tx.outputs[2].lockingBytecode == beaconLock);\n require(tx.outputs[2].value >= beaconDust);\n require(tx.outputs[2].tokenCategory == 0x);\n\n require(tx.outputs.length <= 6);\n if (tx.outputs.length > 3) { require(tx.outputs[3].tokenCategory == 0x); }\n if (tx.outputs.length > 4) { require(tx.outputs[4].tokenCategory == 0x); }\n if (tx.outputs.length > 5) { require(tx.outputs[5].tokenCategory == 0x); }\n }\n\n function refund(pubkey pk, sig s) {\n require(hash160(pk) == buyerPkh);\n require(checkSig(s, pk));\n require(this.age >= refundAfter);\n }\n}\n",
|
||
|
|
"fingerprint": "9c93f44bcd3875104d52642c9bd01751a2198b56dc00aaabd301d616f9047cc3",
|
||
|
|
"debug": {
|
||
|
|
"bytecode": "5779009c63c0519d00c9009d00c800cd537a8800d18800d27b8800d3009d51cd7b8851d1008852cd7b8852cc7ba26952d10088c456a169c453a06353d1008868c454a06354d1008868c455a06355d10088686d755167577a519d5779a988577a577aad557ab26d6d6d5168",
|
||
|
|
"sourceMap": "49:4:70:5;;;;;50:16:50:37;:41::42;:8::44:1;51:26:51:27:0;:16::42:1;:46::47:0;:8::49:1;52:35:52:36:0;:25::61:1;54:27:54:28:0;:16::45:1;:49::57:0;;:8::59:1;55:27:55:28:0;:16::43:1;:8::57;56:27:56:28:0;:16::43:1;:47::61:0;:8::63:1;57:27:57:28:0;:16::41:1;:45::46:0;:8::48:1;59:27:59:28:0;:16::45:1;:49::60:0;:8::62:1;60:27:60:28:0;:16::43:1;:47::49:0;:8::51:1;62:27:62:28:0;:16::45:1;:49::59:0;:8::61:1;63:27:63:28:0;:16::35:1;:39::49:0;:16:::1;:8::51;64:27:64:28:0;:16::43:1;:47::49:0;:8::51:1;66:16:66:33:0;:37::38;:16:::1;:8::40;67:12:67:29:0;:32::33;:12:::1;:35::82:0;:56::57;:45::72:1;:76::78:0;:37::80:1;:35::82;68:12:68:29:0;:32::33;:12:::1;:35::82:0;:56::57;:45::72:1;:76::78:0;:37::80:1;:35::82;69:12:69:29:0;:32::33;:12:::1;:35::82:0;:56::57;:45::72:1;:76::78:0;:37::80:1;:35::82;49:23:70:5;;;:4;72::76::0;;;;73:24:73:26;;:16::27:1;:8::41;74:25:74:26:0;;:28::30;;:8::33:1;75:28:75:39:0;;:8::41:1;72:38:76:5;;;;40:0:77:1",
|
||
|
|
"logs": [],
|
||
|
|
"requires": [
|
||
|
|
{ "ip": 14, "line": 50 },
|
||
|
|
{ "ip": 18, "line": 51 },
|
||
|
|
{ "ip": 25, "line": 54 },
|
||
|
|
{ "ip": 28, "line": 55 },
|
||
|
|
{ "ip": 32, "line": 56 },
|
||
|
|
{ "ip": 36, "line": 57 },
|
||
|
|
{ "ip": 40, "line": 59 },
|
||
|
|
{ "ip": 44, "line": 60 },
|
||
|
|
{ "ip": 48, "line": 62 },
|
||
|
|
{ "ip": 53, "line": 63 },
|
||
|
|
{ "ip": 57, "line": 64 },
|
||
|
|
{ "ip": 61, "line": 66 },
|
||
|
|
{ "ip": 69, "line": 67 },
|
||
|
|
{ "ip": 78, "line": 68 },
|
||
|
|
{ "ip": 87, "line": 69 },
|
||
|
|
{ "ip": 100, "line": 73 },
|
||
|
|
{ "ip": 105, "line": 74 },
|
||
|
|
{ "ip": 108, "line": 75 }
|
||
|
|
]
|
||
|
|
},
|
||
|
|
"compiler": {
|
||
|
|
"name": "cashc",
|
||
|
|
"version": "0.13.3",
|
||
|
|
"options": {
|
||
|
|
"enforceFunctionParameterTypes": true,
|
||
|
|
"enforceLocktimeGuard": true
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"updatedAt": "2026-10-04T14:02:01.200Z"
|
||
|
|
}
|