@fundtokens/builders 0.1.0-rc10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FundTokenTransactionBuilder.js +457 -0
- package/LICENSE +1 -0
- package/PublicFundTransactionBuilder.js +346 -0
- package/README.md +85 -0
- package/art/asset.json +60 -0
- package/art/authhead_vault.json +51 -0
- package/art/fee.json +101 -0
- package/art/fee_minter.json +82 -0
- package/art/fund.json +76 -0
- package/art/manager.json +206 -0
- package/art/mint_inflow.json +84 -0
- package/art/mint_outflow.json +84 -0
- package/art/public.json +149 -0
- package/art/public_vault.json +122 -0
- package/art/simple_minter.json +73 -0
- package/art/simple_vault.json +37 -0
- package/art/startup.json +113 -0
- package/constants.js +1 -0
- package/index.js +18 -0
- package/package.json +21 -0
- package/utils.js +254 -0
package/art/public.json
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contractName": "PublicFund",
|
|
3
|
+
"constructorInputs": [
|
|
4
|
+
{
|
|
5
|
+
"name": "authHeadDestination",
|
|
6
|
+
"type": "bytes"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "publicFundDestination",
|
|
10
|
+
"type": "bytes"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "token",
|
|
14
|
+
"type": "bytes32"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "startupContract",
|
|
18
|
+
"type": "bytes32"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "fundContract",
|
|
22
|
+
"type": "bytes"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"name": "inflowToken",
|
|
26
|
+
"type": "bytes32"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "outflowToken",
|
|
30
|
+
"type": "bytes32"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"abi": [
|
|
34
|
+
{
|
|
35
|
+
"name": "broadcast",
|
|
36
|
+
"inputs": [
|
|
37
|
+
{
|
|
38
|
+
"name": "fund",
|
|
39
|
+
"type": "bytes"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"bytecode": "OP_0 OP_OUTPOINTINDEX OP_0 OP_NUMEQUALVERIFY OP_0 OP_UTXOTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_INPUTINDEX OP_4 OP_SUB OP_UTXOBYTECODE aa20 OP_4 OP_ROLL OP_CAT 87 OP_CAT OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOBYTECODE OP_INPUTINDEX OP_4 OP_ADD OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_INPUTINDEX OP_4 OP_ADD OP_OUTPUTTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_2 OP_PICK OP_2 OP_CAT OP_EQUALVERIFY OP_5 OP_PICK 20 OP_SPLIT OP_OVER OP_0 OP_EQUAL OP_NOT OP_VERIFY OP_OVER OP_0 OP_OUTPOINTTXHASH OP_EQUALVERIFY OP_8 OP_SPLIT OP_SWAP OP_BIN2NUM OP_0 OP_GREATERTHAN OP_VERIFY OP_8 OP_SPLIT OP_DUP OP_SIZE OP_NIP OP_0 OP_GREATERTHAN OP_IF OP_OVER OP_BIN2NUM OP_0 0040075af07507 OP_WITHIN OP_VERIFY OP_0 OP_BEGIN OP_OVER 20 OP_SPLIT OP_DUP OP_8 OP_SPLIT OP_OVER OP_BIN2NUM OP_0 OP_GREATERTHAN OP_VERIFY OP_4 OP_PICK OP_0 OP_EQUAL OP_NOTIF OP_4 OP_PICK 00 OP_CAT OP_BIN2NUM OP_4 OP_PICK 00 OP_CAT OP_BIN2NUM OP_LESSTHAN OP_VERIFY OP_ENDIF OP_DUP OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_3 OP_PICK OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_2DROP OP_2DROP OP_OVER OP_SIZE OP_NIP OP_0 OP_LESSTHANOREQUAL OP_UNTIL OP_DROP OP_ELSE OP_OVER OP_BIN2NUM OP_1 0040075af07507 OP_WITHIN OP_VERIFY OP_ENDIF OP_INPUTINDEX OP_3 OP_ADD OP_OUTPUTBYTECODE aa20 20 OP_11 OP_PICK OP_HASH256 OP_CAT 20 OP_CAT OP_5 OP_ROLL OP_CAT 20 OP_CAT OP_9 OP_ROLL OP_CAT 20 OP_CAT OP_8 OP_ROLL OP_CAT OP_7 OP_ROLL OP_CAT OP_HASH256 OP_CAT 87 OP_CAT OP_EQUALVERIFY OP_INPUTINDEX OP_3 OP_ADD OP_OUTPUTTOKENCATEGORY OP_0 OP_OUTPOINTTXHASH OP_EQUALVERIFY OP_INPUTINDEX OP_3 OP_ADD OP_OUTPUTTOKENAMOUNT ffffffffffffff7f OP_NUMEQUALVERIFY OP_INPUTINDEX OP_5 OP_ADD OP_5 OP_ROLL OP_BEGIN 8000 OP_OVER OP_SIZE OP_NIP OP_MIN OP_2DUP OP_SPLIT OP_4 OP_PICK OP_OUTPUTTOKENCOMMITMENT OP_2 OP_PICK OP_EQUALVERIFY OP_4 OP_PICK OP_OUTPUTBYTECODE OP_8 OP_PICK OP_EQUALVERIFY OP_4 OP_PICK OP_1ADD OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_4 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_2DROP OP_DROP OP_DUP OP_SIZE OP_NIP OP_0 OP_LESSTHANOREQUAL OP_UNTIL OP_1 OP_BEGIN OP_DUP OP_INPUTINDEX OP_4 OP_SUB OP_4 OP_PICK OP_WITHIN OP_NOTIF OP_DUP OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUAL OP_NOTIF OP_DUP OP_OUTPUTTOKENCATEGORY 20 OP_SPLIT OP_DROP OP_0 OP_OUTPOINTTXHASH OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_OUTPUTTOKENCATEGORY 20 OP_SPLIT OP_DROP OP_7 OP_PICK OP_EQUAL OP_NOT OP_VERIFY OP_ENDIF OP_ENDIF OP_DUP OP_1ADD OP_NIP OP_DUP OP_TXOUTPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL OP_2DROP OP_2DROP OP_2DROP OP_DROP OP_1",
|
|
45
|
+
"source": "pragma cashscript ~0.13.0;\r\n\r\n/**\r\n * PublicFund: Broadcasts and validates fund parameters in transaction\r\n * \r\n * Validates fund parameters and chunks them into individual outputs for\r\n * blockchain visibility. This allows external observers to reconstruct fund\r\n * details without accessing the contract directly.\r\n * \r\n * Fund data format:\r\n * [fund_category (32) | fund_amount (8) | satoshis (8) | \r\n * asset1_category (32) | asset1_amount (8) | ... | assetN_category (32) | assetN_amount (8)]\r\n * \r\n * Parameters:\r\n * authHeadDestination: AuthHeadVault output destination (for fund access control)\r\n * token: Genesis transaction hash (fund identifier, part of commitment)\r\n * startupContract: FundStartup contract hash (verifies fund creation came from startup)\r\n * fundContract: Fund manager bytecode template (used in commitment calculation)\r\n * inflowToken: Inflow token category (for transaction manager commitment)\r\n * outflowToken: Outflow token category (for transaction manager commitment)\r\n */\r\ncontract PublicFund(bytes authHeadDestination, bytes publicFundDestination, bytes32 token, bytes32 startupContract, bytes fundContract, bytes32 inflowToken, bytes32 outflowToken)\r\n{ \r\n /**\r\n * broadcast(bytes fund): Validates and broadcasts fund parameters\r\n * \r\n * Chunks fund into up to 128-byte pieces and stores in output NFT commitments.\r\n * Verifies fund parameters (amounts, satoshis, asset sorting) match startup.\r\n * Creates transaction manager contract hash as output.\r\n * \r\n * Validates:\r\n * - Genesis input (index 0) has no tokens and outpointIndex == 0\r\n * - Fund category matches genesis input transaction hash\r\n * - Fund amount > 0\r\n * - Satoshis in valid range\r\n * - Assets sorted ascending by category\r\n * - Each asset amount > 0\r\n * - Transaction manager contract properly calculated from fund parameters\r\n * - No unauthorized token minting\r\n * \r\n * Creates outputs:\r\n * - Output[0]: AuthHeadVault output for fund access control\r\n * - Output[activeInputIndex-4]: Startup contract\r\n * - Output[activeInputIndex+3]: FundContract with verified genesis token\r\n * - Output[activeInputIndex+4]: PublicFund returned\r\n * - Output[activeInputIndex+5]: Fund chunks (128 bytes max each in NFT commitments)\r\n * - Output[activeInputIndex+5+D]: Fund chunks (128 bytes max each in NFT commitments)\r\n */\r\n function broadcast(bytes fund) {\r\n // Verify genesis input (first input) is the confirmed fund creation\r\n require(tx.inputs[0].outpointIndex == 0); // Genesis output\r\n require(tx.inputs[0].tokenCategory == 0x); // No tokens on genesis\r\n\r\n // Output 0 goes to authhead vault (fund access control point)\r\n require(tx.outputs[0].lockingBytecode == authHeadDestination);\r\n require(tx.outputs[0].tokenCategory == 0x);\r\n\r\n // Verify FundStartup input (4 inputs before this PublicFund)\r\n require(tx.inputs[this.activeInputIndex - 4].lockingBytecode == new LockingBytecodeP2SH32(startupContract));\r\n\r\n // PublicFund returns to itself (self) with token tracking\r\n require(tx.inputs[this.activeInputIndex].lockingBytecode == tx.outputs[this.activeInputIndex + 4].lockingBytecode);\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == tx.outputs[this.activeInputIndex + 4].tokenCategory);\r\n // Verify we're holding the \"public\" token (minted with continued capability 0x02)\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == bytes(token + 0x02));\r\n\r\n // Parse and validate fund parameters\r\n bytes nft_fundCategory, bytes nft_next1 = fund.split(32);\r\n // Fund category must be genesis transaction hash (identifies the fund)\r\n require(nft_fundCategory != 0x);\r\n require(nft_fundCategory == tx.inputs[0].outpointTransactionHash);\r\n \r\n // Fund amount (tokens per share) must be > 0\r\n bytes nft_fundAmount, bytes nft_next2 = nft_next1.split(8);\r\n require(int(nft_fundAmount) > 0);\r\n \r\n // Satoshis value for fund (0 or in Bitcoin supply range)\r\n bytes nft_satoshis, bytes nft_assets = nft_next2.split(8);\r\n\r\n // Validate assets (if any exist)\r\n if(nft_assets.length > 0) {\r\n // Satoshis must be valid, greater than or equal to zero\r\n require(within(int(nft_satoshis), 0, 21000000 bitcoin));\r\n \r\n // Verify assets are sorted ascending by category\r\n bytes lastAssetCategory = 0x;\r\n do {\r\n bytes nft_assetCategory, bytes nft_next3 = nft_assets.split(32);\r\n bytes nft_assetAmount, bytes nft_next4 = nft_next3.split(8);\r\n // Each asset must have amount > 0\r\n require(int(nft_assetAmount) > 0);\r\n\r\n // Assets must be in ascending order for deterministic sorting\r\n if(lastAssetCategory != 0x) {\r\n require(int(lastAssetCategory + 0x00) < int(nft_assetCategory + 0x00));\r\n }\r\n\r\n nft_assets = nft_next4;\r\n lastAssetCategory = nft_assetCategory;\r\n } while(nft_assets.length > 0);\r\n } else {\r\n // If no assets, satoshis must be used\r\n require(within(int(nft_satoshis), 1 sats, 21000000 bitcoin)); \r\n }\r\n\r\n // Create transaction manager contract address from fund parameters\r\n // This ensures each fund has a unique manager instance\r\n // Formula: hash256(0x20 + hash256(fund) + 0x20 + fundCategory + 0x20 + outflowToken + 0x20 + inflowToken + fundContract)\r\n require(tx.outputs[this.activeInputIndex + 3].lockingBytecode == new LockingBytecodeP2SH32(hash256(0x20 + hash256(fund) + 0x20 + nft_fundCategory + 0x20 + outflowToken + 0x20 + inflowToken + fundContract)));\r\n // Transaction manager gets fund identifier token (genesis hash)\r\n require(tx.outputs[this.activeInputIndex + 3].tokenCategory == tx.inputs[0].outpointTransactionHash);\r\n // Token amount is max uint64 (indicates continued minting capability)\r\n require(tx.outputs[this.activeInputIndex + 3].tokenAmount == 9223372036854775807); // max uint64\r\n\r\n // Chunk fund into 128-byte pieces and store in output NFT commitments\r\n // Each chunk goes into an output as NFT commitment data\r\n int lastOutput = this.activeInputIndex + 5;\r\n bytes fundRemaining = fund;\r\n do {\r\n // Take up to 128 bytes per chunk (CashScript data limit)\r\n int chunkSize = min(128, fundRemaining.length);\r\n bytes part, bytes fundNext = fundRemaining.split(chunkSize);\r\n // Store chunk in NFT commitment of output\r\n require(tx.outputs[lastOutput].nftCommitment == part);\r\n require(tx.outputs[lastOutput].lockingBytecode == publicFundDestination);\r\n lastOutput = lastOutput + 1;\r\n fundRemaining = fundNext;\r\n } while(fundRemaining.length > 0);\r\n\r\n // Verify no unauthorized token minting\r\n // Check all outputs outside the managed range\r\n int outputIndex = 1; // 0 (authhead) already validated\r\n do {\r\n // Skip outputs we've already validated\r\n if(!within(outputIndex, this.activeInputIndex - 4, lastOutput)) {\r\n if(tx.outputs[outputIndex].tokenCategory != 0x) {\r\n // Prevent minting fund category tokens outside our control\r\n require(tx.outputs[outputIndex].tokenCategory.slice(0, 32) != tx.inputs[0].outpointTransactionHash);\r\n // Prevent minting public/governance tokens outside our control\r\n require(tx.outputs[outputIndex].tokenCategory.slice(0, 32) != token);\r\n }\r\n }\r\n outputIndex = outputIndex + 1;\r\n } while(outputIndex < tx.outputs.length);\r\n }\r\n}\r\n",
|
|
46
|
+
"debug": {
|
|
47
|
+
"bytecode": "00c9009d00ce008800cd8800d10088c05494c702aa20547a7e01877e88c0c7c05493cd88c0cec05493d188c0ce5279527e88557901207f78008791697800c888587f7c8100a069587f76827700a063788100070040075af07507a56900657801207f76587f788100a0695479008764547901007e81547901007e819f696876567a757c6b7c6b7c6b7c6b7c6c6c6c6c5379557a757c6b7c6b7c6b7c6c6c6c6d6d78827700a1667567788151070040075af07507a56968c05393cd02aa2001205b79aa7e01207e557a7e01207e597a7e01207e587a7e577a7eaa7e01877e88c05393d100c888c05393d308ffffffffffffff7f9dc05593557a65028000788277a36e7f5479d25279885479cd58798854798b557a757c6b7c6b7c6b7c6c6c6c76547a757c6b7c6b7c6c6c6d7576827700a166516576c054945479a56476d100876476d101207f7500c887916976d101207f7557798791696868768b7776c4a2666d6d6d7551",
|
|
48
|
+
"sourceMap": "51:26:51:27;:16::42:1;:46::47:0;:8::49:1;52:26:52:27:0;:16::42:1;:46::48:0;:8::50:1;55:27:55:28:0;:16::45:1;:8::70;56:27:56:28:0;:16::43:1;:47::49:0;:8::51:1;59:26:59:47:0;:50::51;:26:::1;:16::68;:72::114:0;:98::113;;:72::114:1;;;:8::116;62:26:62:47:0;:16::64:1;:79::100:0;:103::104;:79:::1;:68::121;:8::123;63:26:63:47:0;:16::62:1;:77::98:0;:101::102;:77:::1;:66::117;:8::119;65:26:65:47:0;:16::62:1;:72::77:0;;:80::84;:72:::1;:8::87;68:50:68:54:0;;:61::63;:50::64:1;70:16:70:32:0;:36::38;:16:::1;;:8::40;71:16:71:32:0;:46::47;:36::72:1;:8::74;74:64:74:65:0;:48::66:1;75:20:75:34:0;:16::35:1;:38::39:0;:16:::1;:8::41;78:63:78:64:0;:47::65:1;81:11:81:21:0;:::28:1;;:31::32:0;:11:::1;:34:101:9:0;83:31:83:43;:27::44:1;:46::47:0;:49::65;:20::66:1;:12::68;86:38:86:40:0;87:12:100:43;88:59:88:69;:76::78;:59::79:1;89:57:89:66:0;:73::74;:57::75:1;91:28:91:43:0;:24::44:1;:47::48:0;:24:::1;:16::50;94:19:94:36:0;;:40::42;:19:::1;::96:17:0;95:32:95:49;;:52::56;:32:::1;:28::57;:64::81:0;;:84::88;:64:::1;:60::89;:28;:20::91;94:44:96:17;98:29:98:38:0;:16::39:1;;;;;;;;;;;;;;;;99:36:99:53:0;;:16::54:1;;;;;;;;;;;;;87:15:100:13;;100:20::30:0;:::37:1;;:40::41:0;87:12::43:1;;81:34:101:9;101:15:104::0;103:31:103:43;:27::44:1;:46::52:0;:54::70;:20::71:1;:12::73;101:15:104:9;109:27:109:48:0;:51::52;:27:::1;:16::69;:73::213:0;:107::111;:122::126;;:114::127:1;:107;:130::134:0;:107:::1;:137::153:0;;:107:::1;:156::160:0;:107:::1;:163::175:0;;:107:::1;:178::182:0;:107:::1;:185::196:0;;:107:::1;:199::211:0;;:107:::1;:99::212;:73::213;;;:8::215;111:27:111:48:0;:51::52;:27:::1;:16::67;:81::82:0;:71::107:1;:8::109;113:27:113:48:0;:51::52;:27:::1;:16::65;:69::88:0;:8::90:1;117:25:117:46:0;:49::50;:25:::1;118:30:118:34:0;;119:8:128:42;121:32:121:35;:37::50;:::57:1;;:28::58;122:41:122:70:0;:::71:1;124:31:124:41:0;;:20::56:1;:60::64:0;;:12::66:1;125:31:125:41:0;;:20::58:1;:62::83:0;;:12::85:1;126:25:126:35:0;;:::39:1;:12::40;;;;;;;;;;;;;127:28:127:36:0;:12::37:1;;;;;;;;;;119:11:128:9;;128:16::29:0;:::36:1;;:39::40:0;119:8::42:1;;132:26:132:27:0;133:8:144:49;135:23:135:34;:36::57;:60::61;:36:::1;:63::73:0;;:16::74:1;:15:142:13:0;136:30:136:41;:19::56:1;:60::62:0;:19:::1;::141:17:0;138:39:138:50;:28::65:1;:75::77:0;:28::78:1;;:92::93:0;:82::118:1;:28;;:20::120;140:39:140:50:0;:28::65:1;:75::77:0;:28::78:1;;:82::87:0;;:28:::1;;:20::89;136:64:141:17;135:76:142:13;143:26:143:37:0;:::41:1;:12::42;144:16:144:27:0;:30::47;133:8::49:1;;49:4:145:5;;;;",
|
|
49
|
+
"logs": [],
|
|
50
|
+
"requires": [
|
|
51
|
+
{
|
|
52
|
+
"ip": 10,
|
|
53
|
+
"line": 51
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"ip": 14,
|
|
57
|
+
"line": 52
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"ip": 17,
|
|
61
|
+
"line": 55
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"ip": 21,
|
|
65
|
+
"line": 56
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"ip": 32,
|
|
69
|
+
"line": 59
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"ip": 39,
|
|
73
|
+
"line": 62
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"ip": 46,
|
|
77
|
+
"line": 63
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"ip": 53,
|
|
81
|
+
"line": 65
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"ip": 62,
|
|
85
|
+
"line": 70
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"ip": 66,
|
|
89
|
+
"line": 71
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"ip": 73,
|
|
93
|
+
"line": 75
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"ip": 87,
|
|
97
|
+
"line": 83
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"ip": 100,
|
|
101
|
+
"line": 91
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"ip": 117,
|
|
105
|
+
"line": 95
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"ip": 166,
|
|
109
|
+
"line": 103
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"ip": 200,
|
|
113
|
+
"line": 109
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"ip": 207,
|
|
117
|
+
"line": 111
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"ip": 213,
|
|
121
|
+
"line": 113
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"ip": 232,
|
|
125
|
+
"line": 124
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"ip": 238,
|
|
129
|
+
"line": 125
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"ip": 298,
|
|
133
|
+
"line": 138
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"ip": 308,
|
|
137
|
+
"line": 140
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
"compiler": {
|
|
142
|
+
"name": "cashc",
|
|
143
|
+
"version": "0.13.0-next.6",
|
|
144
|
+
"options": {
|
|
145
|
+
"enforceFunctionParameterTypes": true
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"updatedAt": "2026-05-06T19:09:26.738Z"
|
|
149
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contractName": "PublicFundVault",
|
|
3
|
+
"constructorInputs": [
|
|
4
|
+
{
|
|
5
|
+
"name": "publicFund",
|
|
6
|
+
"type": "bytes32"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "authorization",
|
|
10
|
+
"type": "bytes32"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"abi": [
|
|
14
|
+
{
|
|
15
|
+
"name": "close",
|
|
16
|
+
"inputs": [
|
|
17
|
+
{
|
|
18
|
+
"name": "hash",
|
|
19
|
+
"type": "bytes"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "prove",
|
|
25
|
+
"inputs": [
|
|
26
|
+
{
|
|
27
|
+
"name": "hash",
|
|
28
|
+
"type": "bytes"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "data",
|
|
34
|
+
"inputs": []
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"bytecode": "OP_2 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_OVER OP_EQUALVERIFY OP_INPUTINDEX OP_0 OP_BEGIN OP_2DUP OP_SWAP OP_UTXOTOKENCOMMITMENT OP_CAT OP_NIP OP_OVER OP_1ADD OP_ROT OP_DROP OP_SWAP OP_OVER OP_TXINPUTCOUNT OP_LESSTHAN OP_2 OP_PICK OP_UTXOTOKENCATEGORY OP_4 OP_PICK OP_EQUAL OP_BOOLAND OP_NOT OP_UNTIL OP_HASH256 OP_5 OP_ROLL OP_EQUALVERIFY OP_0 OP_0 OP_BEGIN OP_DUP OP_UTXOTOKENCATEGORY OP_5 OP_PICK OP_EQUAL OP_IF OP_DUP OP_UTXOTOKENCOMMITMENT OP_8 OP_AND OP_8 OP_EQUAL OP_IF OP_1 OP_ROT OP_DROP OP_SWAP OP_ENDIF OP_ENDIF OP_DUP OP_1ADD OP_NIP OP_DUP OP_TXINPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL OP_SWAP OP_VERIFY OP_0 OP_BEGIN OP_DUP OP_OUTPUTTOKENCATEGORY OP_4 OP_PICK OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_1ADD OP_NIP OP_DUP OP_TXOUTPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE OP_2 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_OVER OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOBYTECODE OP_INPUTINDEX OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_INPUTINDEX OP_OUTPUTTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT OP_INPUTINDEX OP_OUTPUTTOKENCOMMITMENT OP_EQUALVERIFY OP_INPUTINDEX OP_0 OP_BEGIN OP_OVER OP_UTXOBYTECODE OP_2 OP_PICK OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_OVER OP_UTXOTOKENCATEGORY OP_2 OP_PICK OP_OUTPUTTOKENCATEGORY OP_EQUALVERIFY OP_OVER OP_UTXOTOKENCOMMITMENT OP_2 OP_PICK OP_OUTPUTTOKENCOMMITMENT OP_EQUALVERIFY OP_2DUP OP_SWAP OP_UTXOTOKENCOMMITMENT OP_CAT OP_NIP OP_OVER OP_1ADD OP_ROT OP_DROP OP_SWAP OP_OVER OP_TXINPUTCOUNT OP_LESSTHAN OP_2 OP_PICK OP_UTXOTOKENCATEGORY OP_4 OP_PICK OP_EQUAL OP_BOOLAND OP_NOT OP_UNTIL OP_HASH256 OP_5 OP_ROLL OP_EQUALVERIFY OP_0 OP_BEGIN OP_DUP OP_INPUTINDEX OP_3 OP_PICK OP_WITHIN OP_NOTIF OP_DUP OP_UTXOTOKENCATEGORY OP_3 OP_PICK OP_EQUAL OP_NOT OP_VERIFY OP_ENDIF OP_DUP OP_1ADD OP_NIP OP_DUP OP_TXINPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL OP_2DROP OP_2DROP OP_DROP OP_1 OP_ELSE OP_ROT OP_2 OP_NUMEQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOBYTECODE OP_INPUTINDEX OP_1SUB OP_UTXOBYTECODE OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_INPUTINDEX OP_1SUB OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_OUTPOINTTXHASH OP_INPUTINDEX OP_1SUB OP_OUTPOINTTXHASH OP_EQUAL OP_NIP OP_ENDIF OP_ENDIF",
|
|
38
|
+
"source": "pragma cashscript ~0.13.0;\r\n\r\n/**\r\n * PublicFundVault: Fund transparency and proof contract\r\n * \r\n * Extends the authorization pattern established by SimpleVault to manage public fund state.\r\n * Enables transparent on-chain proof of fund composition and controlled fund closure.\r\n * \r\n * Key Features:\r\n * - On-chain asset composition proofs via hash verification\r\n * - Controlled fund closure signal with authorization checks\r\n * - Commitment data chaining for proof continuity\r\n * - Prevents unauthorized token state changes\r\n * \r\n * Parameters:\r\n * publicFund: Token category of the public fund NFT\r\n * authorization: Token category that authorizes fund closure\r\n */\r\ncontract PublicFundVault(bytes32 publicFund, bytes32 authorization)\r\n{\r\n /**\r\n * close(): Permanently closes a public fund data stream by burning all public tokens\r\n * \r\n * Validates and aggregates all publicFund NFT commitment data, verifies the hash,\r\n * confirms authorization (bit 0x08), and burns all publicFund tokens from outputs.\r\n * \r\n * Notes:\r\n * - Fund data can be recovered from transaction history even after burning\r\n * - Intended to signal for rare closure events only\r\n * - Requires authorization token with bit 0x08 (fund closure permission)\r\n * \r\n * Parameters:\r\n * hash: Expected hash256 of concatenated fund commitment data\r\n * \r\n * Constraints:\r\n * - All publicFund inputs must be processed sequentially\r\n * - Authorization token (bit 0x08) must be present somewhere in the transaction\r\n * - No publicFund tokens allowed in any output (complete burn)\r\n */\r\n function close(bytes hash) {\r\n // sanity check\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == publicFund);\r\n\r\n // 1. build data\r\n int fundIndex = this.activeInputIndex;\r\n bytes fund = 0x;\r\n do {\r\n fund = fund + tx.inputs[fundIndex].nftCommitment;\r\n fundIndex = fundIndex + 1;\r\n } while(fundIndex < tx.inputs.length && tx.inputs[fundIndex].tokenCategory == publicFund);\r\n\r\n // 2. hash and verify\r\n require(hash256(fund) == hash);\r\n\r\n // 3. check for authorization\r\n bool authorized = false;\r\n int inputIndex = 0;\r\n do {\r\n if(tx.inputs[inputIndex].tokenCategory == authorization) {\r\n if((tx.inputs[inputIndex].nftCommitment & bytes(0x08)) == 0x08) {\r\n authorized = true;\r\n }\r\n }\r\n inputIndex = inputIndex + 1;\r\n } while(inputIndex < tx.inputs.length);\r\n require(authorized);\r\n\r\n // 4. burn the tokens\r\n int outputIndex = 0;\r\n do {\r\n require(tx.outputs[outputIndex].tokenCategory != publicFund);\r\n outputIndex = outputIndex + 1;\r\n } while(outputIndex < tx.outputs.length);\r\n }\r\n\r\n /**\r\n * prove(): Proves fund composition on-chain via hash verification\r\n * \r\n * Validates that all publicFund inputs are properly forwarded to matching outputs,\r\n * aggregates their commitment data, and verifies the hash matches expected state.\r\n * Ensures no other publicFund proofs exist in the same transaction.\r\n * \r\n * This pattern establishes an immutable proof chain:\r\n * - Input commitment data must exactly match output commitment data\r\n * - All intermediate UTXOs are validated for consistency\r\n * - Hash verification prevents tampering with fund state\r\n * \r\n * Parameters:\r\n * hash: Expected hash256 of concatenated fund commitment data\r\n * \r\n * Constraints:\r\n * - Active input (this UTXO) must forward without changes\r\n * - All consecutive publicFund inputs/outputs must be in matching positions\r\n * - Commitment data is immutable (same in/out)\r\n * - No other publicFund proofs allowed in same transaction\r\n */\r\n function prove(bytes hash) {\r\n // 4. forward input\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == publicFund);\r\n require(tx.inputs[this.activeInputIndex].lockingBytecode == tx.outputs[this.activeInputIndex].lockingBytecode);\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == tx.outputs[this.activeInputIndex].tokenCategory);\r\n require(tx.inputs[this.activeInputIndex].nftCommitment == tx.outputs[this.activeInputIndex].nftCommitment);\r\n\r\n // 1. build data\r\n int fundIndex = this.activeInputIndex;\r\n bytes fund = 0x;\r\n do {\r\n require(tx.inputs[fundIndex].lockingBytecode == tx.outputs[fundIndex].lockingBytecode);\r\n require(tx.inputs[fundIndex].tokenCategory == tx.outputs[fundIndex].tokenCategory);\r\n require(tx.inputs[fundIndex].nftCommitment == tx.outputs[fundIndex].nftCommitment);\r\n\r\n fund = fund + tx.inputs[fundIndex].nftCommitment;\r\n fundIndex = fundIndex + 1;\r\n } while(fundIndex < tx.inputs.length && tx.inputs[fundIndex].tokenCategory == publicFund);\r\n\r\n // 2. hash and verify\r\n require(hash256(fund) == hash);\r\n\r\n // 3. no more proofs in the tx\r\n int inputIndex = 0;\r\n do {\r\n if(!within(inputIndex, this.activeInputIndex, fundIndex)) {\r\n require(tx.inputs[inputIndex].tokenCategory != publicFund);\r\n }\r\n inputIndex = inputIndex + 1;\r\n } while(inputIndex < tx.inputs.length);\r\n }\r\n\r\n /**\r\n * data(): Validates commitment data continuity in the proof chain\r\n * \r\n * Ensures this UTXO is part of a continuous chain of publicFund proofs\r\n * by verifying it was created from the previous input and will be followed\r\n * by the next proof in the sequence.\r\n * \r\n * Used to:\r\n * - Link proof UTXOs together in a chain\r\n * - Maintain commitment data lineage\r\n * - Prevent proof interruption or substitution\r\n * \r\n * Constraints:\r\n * - This input must contain publicFund token\r\n * - Previous input must have identical locking bytecode\r\n * - Previous input must have identical token category\r\n * - Previous input must be from the same transaction (outpointTransactionHash)\r\n */\r\n function data() {\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == publicFund);\r\n require(tx.inputs[this.activeInputIndex].lockingBytecode == tx.inputs[this.activeInputIndex - 1].lockingBytecode);\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == tx.inputs[this.activeInputIndex - 1].tokenCategory);\r\n require(tx.inputs[this.activeInputIndex].outpointTransactionHash == tx.inputs[this.activeInputIndex - 1].outpointTransactionHash);\r\n }\r\n}",
|
|
39
|
+
"debug": {
|
|
40
|
+
"bytecode": "5279009c63c0ce7888c000656e7ccf7e77788b7b757c78c39f5279ce5479879a9166aa557a8800006576ce5579876376cf5884588763517b757c6868768b7776c3a2667c69006576d15479879169768b7776c4a2666d6d6d51675279519c63c0ce7888c0c7c0cd88c0cec0d188c0cfc0d288c0006578c75279cd8878ce5279d18878cf5279d2886e7ccf7e77788b7b757c78c39f5279ce5479879a9166aa557a88006576c05379a56476ce537987916968768b7776c3a2666d6d7551677b529dc0ce88c0c7c08cc788c0cec08cce88c0c8c08cc887776868",
|
|
41
|
+
"sourceMap": "40:4:74:5;;;;;42:26:42:47;:16::62:1;:66::76:0;:8::78:1;45:24:45:45:0;46:21:46:23;47:8:50:98;48:19:48:45;;:26::60:1;:19;:12::61;49:24:49:33:0;:::37:1;:12::38;;;50:16:50:25:0;:28::44;:16:::1;:58::67:0;;:48::82:1;:86::96:0;;:48:::1;:16;47:8::98;;53:16:53:29;:33::37:0;;:8::39:1;56:26:56:31:0;57:25:57:26;58:8:65:47;59:25:59:35;:15::50:1;:54::67:0;;:15:::1;:69:63:13:0;60:30:60:40;:20::55:1;:64::68:0;:20::69:1;:74::78:0;:19:::1;:80:62:17:0;61:33:61:37;:20::38:1;;;60:80:62:17;59:69:63:13;64:25:64:35:0;:::39:1;:12::40;65:16:65:26:0;:29::45;58:8::47:1;;66:16:66:26:0;:8::28:1;69:26:69:27:0;70:8:73:49;71:31:71:42;:20::57:1;:61::71:0;;:20:::1;;:12::73;72:26:72:37:0;:::41:1;:12::42;73:16:73:27:0;:30::47;70:8::49:1;;40:4:74:5;;;;;97::127::0;;;;;99:26:99:47;:16::62:1;:66::76:0;:8::78:1;100:26:100:47:0;:16::64:1;:79::100:0;:68::117:1;:8::119;101:26:101:47:0;:16::62:1;:77::98:0;:66::113:1;:8::115;102:26:102:47:0;:16::62:1;:77::98:0;:66::113:1;:8::115;105:24:105:45:0;106:21:106:23;107:8:114:98;108:30:108:39;:20::56:1;:71::80:0;;:60::97:1;:12::99;109:30:109:39:0;:20::54:1;:69::78:0;;:58::93:1;:12::95;110:30:110:39:0;:20::54:1;:69::78:0;;:58::93:1;:12::95;112:19:112:45:0;;:26::60:1;:19;:12::61;113:24:113:33:0;:::37:1;:12::38;;;114:16:114:25:0;:28::44;:16:::1;:58::67:0;;:48::82:1;:86::96:0;;:48:::1;:16;107:8::98;;117:16:117:29;:33::37:0;;:8::39:1;120:25:120:26:0;121:8:126:47;122:23:122:33;:35::56;:58::67;;:16::68:1;:15:124:13:0;123:34:123:44;:24::59:1;:63::73:0;;:24:::1;;:16::75;122:70:124:13;125:25:125:35:0;:::39:1;:12::40;126:16:126:26:0;:29::45;121:8::47:1;;97:4:127:5;;;;;147::152::0;;;148:26:148:47;:16::62:1;:8::78;149:26:149:47:0;:16::64:1;:78::99:0;:::103:1;:68::120;:8::122;150:26:150:47:0;:16::62:1;:76::97:0;:::101:1;:66::116;:8::118;151:26:151:47:0;:16::72:1;:86::107:0;:::111:1;:76::136;:8::138;147:4:152:5;19:0:153:1;",
|
|
42
|
+
"logs": [],
|
|
43
|
+
"requires": [
|
|
44
|
+
{
|
|
45
|
+
"ip": 10,
|
|
46
|
+
"line": 42
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"ip": 39,
|
|
50
|
+
"line": 53
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"ip": 70,
|
|
54
|
+
"line": 66
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"ip": 79,
|
|
58
|
+
"line": 71
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"ip": 100,
|
|
62
|
+
"line": 99
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"ip": 105,
|
|
66
|
+
"line": 100
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"ip": 110,
|
|
70
|
+
"line": 101
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"ip": 115,
|
|
74
|
+
"line": 102
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"ip": 124,
|
|
78
|
+
"line": 108
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"ip": 130,
|
|
82
|
+
"line": 109
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"ip": 136,
|
|
86
|
+
"line": 110
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"ip": 162,
|
|
90
|
+
"line": 117
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"ip": 177,
|
|
94
|
+
"line": 123
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"ip": 196,
|
|
98
|
+
"line": 148
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"ip": 202,
|
|
102
|
+
"line": 149
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"ip": 208,
|
|
106
|
+
"line": 150
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"ip": 215,
|
|
110
|
+
"line": 151
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
"compiler": {
|
|
115
|
+
"name": "cashc",
|
|
116
|
+
"version": "0.13.0-next.6",
|
|
117
|
+
"options": {
|
|
118
|
+
"enforceFunctionParameterTypes": true
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"updatedAt": "2026-05-06T19:09:28.679Z"
|
|
122
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contractName": "SimpleMinter",
|
|
3
|
+
"constructorInputs": [
|
|
4
|
+
{
|
|
5
|
+
"name": "authorization",
|
|
6
|
+
"type": "bytes32"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "token",
|
|
10
|
+
"type": "bytes32"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "destination",
|
|
14
|
+
"type": "bytes"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"abi": [
|
|
18
|
+
{
|
|
19
|
+
"name": "mint",
|
|
20
|
+
"inputs": []
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"bytecode": "OP_INPUTINDEX OP_UTXOBYTECODE OP_INPUTINDEX OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY 20 OP_SPLIT OP_DROP OP_2 OP_PICK OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_INPUTINDEX OP_OUTPUTTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT OP_INPUTINDEX OP_OUTPUTTOKENCOMMITMENT OP_EQUALVERIFY OP_0 OP_0 OP_BEGIN OP_DUP OP_UTXOTOKENCATEGORY OP_3 OP_PICK OP_EQUAL OP_IF OP_DUP OP_UTXOTOKENCOMMITMENT OP_1 OP_AND OP_1 OP_EQUAL OP_IF OP_1 OP_ROT OP_DROP OP_SWAP OP_ENDIF OP_ENDIF OP_DUP OP_1ADD OP_NIP OP_DUP OP_TXINPUTCOUNT OP_LESSTHAN OP_2 OP_PICK OP_NOT OP_BOOLAND OP_NOT OP_UNTIL OP_SWAP OP_VERIFY OP_0 OP_BEGIN OP_DUP OP_INPUTINDEX OP_NUMNOTEQUAL OP_OVER OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUAL OP_NOT OP_BOOLAND OP_IF OP_DUP OP_OUTPUTTOKENCATEGORY 20 OP_SPLIT OP_DROP OP_4 OP_PICK OP_EQUAL OP_IF OP_DUP OP_OUTPUTBYTECODE OP_5 OP_PICK OP_EQUALVERIFY OP_DUP OP_OUTPUTTOKENCATEGORY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_DUP OP_OUTPUTTOKENCOMMITMENT OP_0 OP_EQUALVERIFY OP_ENDIF OP_ENDIF OP_DUP OP_1ADD OP_NIP OP_DUP OP_TXOUTPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL OP_2DROP OP_2DROP OP_DROP OP_1",
|
|
24
|
+
"source": "pragma cashscript ~0.13.0;\r\n\r\n/**\r\n * SimpleMinter: Owner-controlled token minting\r\n * \r\n * Allows an authorized user to mint new tokens to a specified destination.\r\n * Used for holding and creating inflow, outflow, and public fund tokens during system \r\n * initialization and future system scaling.\r\n * \r\n * Parameters:\r\n * authorization: Token category that authorizes minting (checked in any input)\r\n * token: Token category being minted\r\n * destination: Locking bytecode where minted tokens are sent\r\n */\r\ncontract SimpleMinter(bytes32 authorization, bytes32 token, bytes destination)\r\n{\r\n /**\r\n * mint(): Mints new tokens to the destination\r\n * \r\n * Ensures:\r\n * - This contract returns to itself (locked pattern prevents misuse)\r\n * - Owner authorization is present in transaction inputs (bit 0x01)\r\n * - All minted tokens go to the specified destination\r\n * - NFT commitments are preserved if present\r\n */\r\n function mint() {\r\n // Contract must return to itself (locked pattern)\r\n require(tx.inputs[this.activeInputIndex].lockingBytecode == tx.outputs[this.activeInputIndex].lockingBytecode);\r\n // Verify this is the minting token\r\n require(tx.inputs[this.activeInputIndex].tokenCategory.slice(0, 32) == token);\r\n \r\n // Keep the minting token for future minting\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == tx.outputs[this.activeInputIndex].tokenCategory);\r\n \r\n // Preserve NFT commitment (e.g., for minting capability)\r\n require(tx.inputs[this.activeInputIndex].nftCommitment == tx.outputs[this.activeInputIndex].nftCommitment);\r\n\r\n // Check for owner authorization in ANY input\r\n // Bit 0x01 in commitment indicates minting authorization\r\n bool authorized = false;\r\n int inputIndex = 0;\r\n do {\r\n if(tx.inputs[inputIndex].tokenCategory == authorization) {\r\n if((tx.inputs[inputIndex].nftCommitment & bytes(0x01)) == 0x01) {\r\n authorized = true; // Owner token found - authorized\r\n }\r\n }\r\n inputIndex = inputIndex + 1;\r\n } while(inputIndex < tx.inputs.length && !authorized);\r\n require(authorized, \"unauthorized user\");\r\n\r\n\r\n // Verify all outputs minting this token go to the destination\r\n int outputIndex = 0;\r\n do {\r\n if(outputIndex != this.activeInputIndex && tx.outputs[outputIndex].tokenCategory != 0x) {\r\n // If output is minting our token category\r\n if(tx.outputs[outputIndex].tokenCategory.slice(0, 32) == token) {\r\n // Ensure it goes to the specified destination\r\n require(tx.outputs[outputIndex].lockingBytecode == destination);\r\n // Token category must match for consistency\r\n require(tx.outputs[outputIndex].tokenCategory == tx.inputs[this.activeInputIndex].tokenCategory);\r\n // Minted tokens have no NFT commitment\r\n require(tx.outputs[outputIndex].nftCommitment == 0x);\r\n }\r\n }\r\n outputIndex = outputIndex + 1;\r\n } while(outputIndex < tx.outputs.length);\r\n }\r\n}",
|
|
25
|
+
"debug": {
|
|
26
|
+
"bytecode": "c0c7c0cd88c0ce01207f75527988c0cec0d188c0cfc0d28800006576ce5379876376cf5184518763517b757c6868768b7776c39f5279919a91667c69006576c09e78d10087919a6376d101207f755479876376cd55798876d1c0ce8876d200886868768b7776c4a2666d6d7551",
|
|
27
|
+
"sourceMap": "28:26:28:47;:16::64:1;:79::100:0;:68::117:1;:8::119;30:26:30:47:0;:16::62:1;:72::74:0;:16::75:1;;:79::84:0;;:8::86:1;33:26:33:47:0;:16::62:1;:77::98:0;:66::113:1;:8::115;36:26:36:47:0;:16::62:1;:77::98:0;:66::113:1;:8::115;40:26:40:31:0;41:25:41:26;42:8:49:62;43:25:43:35;:15::50:1;:54::67:0;;:15:::1;:69:47:13:0;44:30:44:40;:20::55:1;:64::68:0;:20::69:1;:74::78:0;:19:::1;:80:46:17:0;45:33:45:37;:20::38:1;;;44:80:46:17;43:69:47:13;48:25:48:35:0;:::39:1;:12::40;49:16:49:26:0;:29::45;:16:::1;:50::60:0;;:49:::1;:16;42:8::62;;50:16:50:26:0;:8::49:1;54:26:54:27:0;55:8:68:49;56:15:56:26;:30::51;:15:::1;:66::77:0;:55::92:1;:96::98:0;:55:::1;;:15;:100:66:13:0;58:30:58:41;:19::56:1;:66::68:0;:19::69:1;;:73::78:0;;:19:::1;:80:65:17:0;60:39:60:50;:28::67:1;:71::82:0;;:20::84:1;62:39:62:50:0;:28::65:1;:79::100:0;:69::115:1;:20::117;64:39:64:50:0;:28::65:1;:69::71:0;:20::73:1;58:80:65:17;56:100:66:13;67:26:67:37:0;:::41:1;:12::42;68:16:68:27:0;:30::47;55:8::49:1;;26:4:69:5;;;",
|
|
28
|
+
"logs": [],
|
|
29
|
+
"requires": [
|
|
30
|
+
{
|
|
31
|
+
"ip": 7,
|
|
32
|
+
"line": 28
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"ip": 15,
|
|
36
|
+
"line": 30
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"ip": 20,
|
|
40
|
+
"line": 33
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"ip": 25,
|
|
44
|
+
"line": 36
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"ip": 61,
|
|
48
|
+
"line": 50,
|
|
49
|
+
"message": "unauthorized user"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"ip": 87,
|
|
53
|
+
"line": 60
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"ip": 92,
|
|
57
|
+
"line": 62
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"ip": 96,
|
|
61
|
+
"line": 64
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
},
|
|
65
|
+
"compiler": {
|
|
66
|
+
"name": "cashc",
|
|
67
|
+
"version": "0.13.0-next.6",
|
|
68
|
+
"options": {
|
|
69
|
+
"enforceFunctionParameterTypes": true
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"updatedAt": "2026-05-06T19:09:29.336Z"
|
|
73
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contractName": "SimpleVault",
|
|
3
|
+
"constructorInputs": [
|
|
4
|
+
{
|
|
5
|
+
"name": "authToken",
|
|
6
|
+
"type": "bytes32"
|
|
7
|
+
}
|
|
8
|
+
],
|
|
9
|
+
"abi": [
|
|
10
|
+
{
|
|
11
|
+
"name": "release",
|
|
12
|
+
"inputs": []
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"bytecode": "OP_0 OP_0 OP_BEGIN OP_DUP OP_UTXOTOKENCATEGORY OP_3 OP_PICK OP_EQUAL OP_IF OP_DUP OP_UTXOTOKENCOMMITMENT 80 OP_AND 80 OP_EQUAL OP_IF OP_1 OP_ROT OP_DROP OP_SWAP OP_ENDIF OP_ENDIF OP_DUP OP_1ADD OP_NIP OP_DUP OP_TXINPUTCOUNT OP_LESSTHAN OP_2 OP_PICK OP_NOT OP_BOOLAND OP_NOT OP_UNTIL OP_DROP OP_NIP",
|
|
16
|
+
"source": "pragma cashscript ~0.13.0;\r\n\r\n/**\r\n * SimpleVault: Authorization-gated custody contract\r\n * \r\n * Holds assets that can only be spent when a specific token is present in the transaction.\r\n * Used for:\r\n * - Owner token custody (prevents accidental spending)\r\n * - Fee collection vault\r\n * - Simple authorization gates\r\n * \r\n * Parameters:\r\n * authToken: Token category that authorizes spending\r\n */\r\ncontract SimpleVault(bytes32 authToken)\r\n{\r\n /**\r\n * release(): Allows spending only when authToken is present\r\n * \r\n * Ensures that ANY transaction spending this UTXO must include\r\n * the authToken in one of its inputs. Checks for bit 0x80 (vault release permission)\r\n * in the NFT commitment to verify proper authorization capability.\r\n */\r\n function release() {\r\n // Check if authorization token is present in ANY input\r\n bool authorized = false;\r\n int inputIndex = 0;\r\n do {\r\n if(tx.inputs[inputIndex].tokenCategory == authToken) {\r\n // Bit 0x80 in commitment indicates vault release authorization\r\n if((tx.inputs[inputIndex].nftCommitment & bytes(0x80)) == 0x80) {\r\n authorized = true; // Found the authorization token\r\n }\r\n }\r\n inputIndex = inputIndex + 1;\r\n } while(inputIndex < tx.inputs.length && !authorized);\r\n \r\n // Transaction must have authorization to proceed\r\n require(authorized, \"unauthorized user\");\r\n }\r\n}",
|
|
17
|
+
"debug": {
|
|
18
|
+
"bytecode": "00006576ce5379876376cf01808401808763517b757c6868768b7776c39f5279919a91667577",
|
|
19
|
+
"sourceMap": "26:26:26:31;27:25:27:26;28:8:36:62;29:25:29:35;:15::50:1;:54::63:0;;:15:::1;:65:34:13:0;31:30:31:40;:20::55:1;:64::68:0;:20::69:1;:74::78:0;:19:::1;:80:33:17:0;32:33:32:37;:20::38:1;;;31:80:33:17;29:65:34:13;35:25:35:35:0;:::39:1;:12::40;36:16:36:26:0;:29::45;:16:::1;:50::60:0;;:49:::1;:16;28:8::62;;24:4:40:5;",
|
|
20
|
+
"logs": [],
|
|
21
|
+
"requires": [
|
|
22
|
+
{
|
|
23
|
+
"ip": 35,
|
|
24
|
+
"line": 39,
|
|
25
|
+
"message": "unauthorized user"
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"compiler": {
|
|
30
|
+
"name": "cashc",
|
|
31
|
+
"version": "0.13.0-next.6",
|
|
32
|
+
"options": {
|
|
33
|
+
"enforceFunctionParameterTypes": true
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"updatedAt": "2026-05-06T19:09:28.170Z"
|
|
37
|
+
}
|
package/art/startup.json
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contractName": "FundStartup",
|
|
3
|
+
"constructorInputs": [
|
|
4
|
+
{
|
|
5
|
+
"name": "fee",
|
|
6
|
+
"type": "bytes32"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"name": "inflowToken",
|
|
10
|
+
"type": "bytes32"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "outflowToken",
|
|
14
|
+
"type": "bytes32"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"abi": [
|
|
18
|
+
{
|
|
19
|
+
"name": "start",
|
|
20
|
+
"inputs": [
|
|
21
|
+
{
|
|
22
|
+
"name": "fund",
|
|
23
|
+
"type": "bytes"
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"bytecode": "OP_INPUTINDEX OP_UTXOBYTECODE OP_INPUTINDEX OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_INPUTINDEX OP_OUTPUTTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_UTXOTOKENCOMMITMENT OP_INPUTINDEX OP_OUTPUTTOKENCOMMITMENT OP_EQUALVERIFY OP_3 OP_PICK 20 OP_SPLIT OP_8 OP_SPLIT OP_SWAP OP_BIN2NUM OP_0 OP_GREATERTHAN OP_VERIFY OP_8 OP_SPLIT OP_SWAP OP_BIN2NUM OP_0 0040075af07507 OP_WITHIN OP_VERIFY OP_0 OP_BEGIN OP_OVER OP_SIZE OP_NIP OP_0 OP_GREATERTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER 20 OP_SPLIT OP_DUP OP_8 OP_SPLIT OP_OVER OP_BIN2NUM OP_0 OP_GREATERTHAN OP_VERIFY OP_4 OP_PICK OP_0 OP_EQUAL OP_NOTIF OP_4 OP_PICK 00 OP_CAT OP_BIN2NUM OP_4 OP_PICK 00 OP_CAT OP_BIN2NUM OP_LESSTHAN OP_VERIFY OP_ENDIF OP_DUP OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_3 OP_PICK OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_2DROP OP_2DROP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_INPUTINDEX OP_1ADD OP_UTXOTOKENCATEGORY OP_5 OP_PICK OP_2 OP_CAT OP_EQUALVERIFY OP_INPUTINDEX OP_2 OP_ADD OP_UTXOTOKENCATEGORY OP_6 OP_PICK OP_2 OP_CAT OP_EQUALVERIFY OP_INPUTINDEX OP_3 OP_ADD OP_UTXOBYTECODE aa20 OP_5 OP_ROLL OP_CAT 87 OP_CAT OP_EQUALVERIFY OP_INPUTINDEX OP_3 OP_ADD OP_UTXOBYTECODE OP_INPUTINDEX OP_3 OP_ADD OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_INPUTINDEX OP_5 OP_ADD OP_OUTPUTTOKENCATEGORY OP_4 OP_PICK OP_EQUALVERIFY OP_INPUTINDEX OP_5 OP_ADD OP_OUTPUTTOKENCOMMITMENT OP_3 OP_PICK OP_7 OP_PICK OP_HASH256 OP_CAT OP_EQUALVERIFY OP_INPUTINDEX OP_6 OP_ADD OP_OUTPUTTOKENCATEGORY OP_5 OP_PICK OP_EQUALVERIFY OP_INPUTINDEX OP_6 OP_ADD OP_OUTPUTTOKENCOMMITMENT OP_3 OP_ROLL OP_6 OP_ROLL OP_HASH256 OP_CAT OP_EQUALVERIFY OP_0 OP_BEGIN OP_DUP OP_INPUTINDEX OP_INPUTINDEX OP_7 OP_ADD OP_WITHIN OP_NOTIF OP_DUP OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUAL OP_NOTIF OP_DUP OP_OUTPUTTOKENCATEGORY 20 OP_SPLIT OP_DROP OP_4 OP_PICK OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_OUTPUTTOKENCATEGORY 20 OP_SPLIT OP_DROP OP_5 OP_PICK OP_EQUAL OP_NOT OP_VERIFY OP_ENDIF OP_ENDIF OP_DUP OP_1ADD OP_NIP OP_DUP OP_TXOUTPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL OP_2DROP OP_2DROP OP_DROP OP_1",
|
|
29
|
+
"source": "pragma cashscript ~0.13.0;\r\n\r\n/**\r\n * FundStartup: Validates and initializes a new fund\r\n * \r\n * Called once during fund creation. Mints inflow/outflow tokens and validates\r\n * all fund parameters including amounts, satoshis, and asset ordering.\r\n * \r\n * Fund data format (passed as bytes):\r\n * [fund_category (32) | fund_amount (8) | satoshis (8) | \r\n * asset1_category (32) | asset1_amount (8) | ... | assetN_category (32) | assetN_amount (8)]\r\n * \r\n * Parameters:\r\n * fee: Fee contract hash (for fee input verification)\r\n * inflowToken: Inflow token category to mint (with minting capability)\r\n * outflowToken: Outflow token category to mint (with minting capability)\r\n */\r\ncontract FundStartup(bytes32 fee, bytes32 inflowToken, bytes32 outflowToken)\r\n{\r\n /**\r\n * start(bytes fund): Validates fund parameters and mints tokens\r\n * \r\n * Validates:\r\n * - Fund amount > 0\r\n * - Satoshis in valid range\r\n * - Assets are sorted by category ascending\r\n * - Each asset amount > 0\r\n * \r\n * Creates:\r\n * - Inflow token NFT with fund commitment\r\n * - Outflow token NFT with fund commitment\r\n */\r\n function start(bytes fund) {\r\n // This startup UTXO returns to itself\r\n require(tx.inputs[this.activeInputIndex].lockingBytecode == tx.outputs[this.activeInputIndex].lockingBytecode);\r\n require(tx.inputs[this.activeInputIndex].tokenCategory == tx.outputs[this.activeInputIndex].tokenCategory);\r\n require(tx.inputs[this.activeInputIndex].nftCommitment == tx.outputs[this.activeInputIndex].nftCommitment);\r\n\r\n // Parse fund parameters from commitment bytes\r\n bytes nft_fundCategory, bytes nft_next1 = fund.split(32);\r\n bytes nft_fundAmount, bytes nft_next2 = nft_next1.split(8);\r\n // Fund amount must be > 0 (determines token divisor)\r\n require(int(nft_fundAmount) > 0);\r\n bytes nft_satoshis, bytes nft_assets = nft_next2.split(8);\r\n // Satoshis must be within Bitcoin supply range (0 to 21 million BTC)\r\n // Note: PublicFund contract enforces stricter limits based on asset composition\r\n require(within(int(nft_satoshis), 0, 2100000000000000));\r\n\r\n // Validate asset sorting and amounts\r\n bytes lastAssetCategory = 0x;\r\n while(nft_assets.length > 0) {\r\n bytes nft_assetCategory, bytes nft_next3 = nft_assets.split(32);\r\n bytes nft_assetAmount, bytes nft_next4 = nft_next3.split(8);\r\n // Each asset amount must be > 0\r\n require(int(nft_assetAmount) > 0);\r\n\r\n // Assets must be in ascending order by category\r\n if(lastAssetCategory != 0x) {\r\n require(int(lastAssetCategory + 0x00) < int(nft_assetCategory + 0x00));\r\n }\r\n\r\n nft_assets = nft_next4;\r\n lastAssetCategory = nft_assetCategory;\r\n }\r\n\r\n // Verify inflow token input (with minting capability)\r\n require(tx.inputs[this.activeInputIndex + 1].tokenCategory == bytes(inflowToken + 0x02));\r\n // Verify outflow token input (with minting capability)\r\n require(tx.inputs[this.activeInputIndex + 2].tokenCategory == bytes(outflowToken + 0x02));\r\n\r\n // Verify fee contract input\r\n require(tx.inputs[this.activeInputIndex + 3].lockingBytecode == new LockingBytecodeP2SH32(fee));\r\n require(tx.inputs[this.activeInputIndex + 3].lockingBytecode == tx.outputs[this.activeInputIndex + 3].lockingBytecode); // sends back to self, it's paid\r\n\r\n // Mint inflow token with fund commitment (fund_category | fund_hash)\r\n require(tx.outputs[this.activeInputIndex + 5].tokenCategory == inflowToken);\r\n require(tx.outputs[this.activeInputIndex + 5].nftCommitment == bytes(nft_fundCategory + hash256(fund)));\r\n \r\n // Mint outflow token with fund commitment\r\n require(tx.outputs[this.activeInputIndex + 6].tokenCategory == outflowToken);\r\n require(tx.outputs[this.activeInputIndex + 6].nftCommitment == bytes(nft_fundCategory + hash256(fund)));\r\n\r\n // Ensure no other outputs mint inflow/outflow tokens\r\n int outputIndex = 0;\r\n do {\r\n if(!within(outputIndex, this.activeInputIndex, this.activeInputIndex + 7)) {\r\n if(tx.outputs[outputIndex].tokenCategory != 0x) {\r\n // No other outputs can mint inflow or outflow tokens\r\n require(tx.outputs[outputIndex].tokenCategory.slice(0, 32) != inflowToken);\r\n require(tx.outputs[outputIndex].tokenCategory.slice(0, 32) != outflowToken);\r\n }\r\n }\r\n outputIndex = outputIndex + 1;\r\n } while(outputIndex < tx.outputs.length);\r\n }\r\n}",
|
|
30
|
+
"debug": {
|
|
31
|
+
"bytecode": "c0c7c0cd88c0cec0d188c0cfc0d288537901207f587f7c8100a069587f7c8100070040075af07507a569006578827700a0766b637801207f76587f788100a0695479008764547901007e81547901007e819f696876567a757c6b7c6b7c6b7c6b7c6c6c6c6c5379557a757c6b7c6b7c6b7c6c6c6c6d6d686c9166c08bce5579527e88c05293ce5679527e88c05393c702aa20557a7e01877e88c05393c7c05393cd88c05593d1547988c05593d253795779aa7e88c05693d1557988c05693d2537a567aaa7e88006576c0c05793a56476d100876476d101207f75547987916976d101207f7555798791696868768b7776c4a2666d6d7551",
|
|
32
|
+
"sourceMap": "35:26:35:47;:16::64:1;:79::100:0;:68::117:1;:8::119;36:26:36:47:0;:16::62:1;:77::98:0;:66::113:1;:8::115;37:26:37:47:0;:16::62:1;:77::98:0;:66::113:1;:8::115;40:50:40:54:0;;:61::63;:50::64:1;41:64:41:65:0;:48::66:1;43:20:43:34:0;:16::35:1;:38::39:0;:16:::1;:8::41;44:63:44:64:0;:47::65:1;47:27:47:39:0;:23::40:1;:42::43:0;:45::61;:16::62:1;:8::64;50:34:50:36:0;51:8:64:9;:14:51:24;:::31:1;;:34::35:0;:14:::1;;;:37:64:9:0;52:55:52:65;:72::74;:55::75:1;53:53:53:62:0;:69::70;:53::71:1;55:24:55:39:0;:20::40:1;:43::44:0;:20:::1;:12::46;58:15:58:32:0;;:36::38;:15:::1;::60:13:0;59:28:59:45;;:48::52;:28:::1;:24::53;:60::77:0;;:80::84;:60:::1;:56::85;:24;:16::87;58:40:60:13;62:25:62:34:0;:12::35:1;;;;;;;;;;;;;;;;63:32:63:49:0;;:12::50:1;;;;;;;;;;;;;51:37:64:9;;;;:8;;67:26:67:47:0;:::51:1;:16::66;:76::87:0;;:90::94;:76:::1;:8::97;69:26:69:47:0;:50::51;:26:::1;:16::66;:76::88:0;;:91::95;:76:::1;:8::98;72:26:72:47:0;:50::51;:26:::1;:16::68;:72::102:0;:98::101;;:72::102:1;;;:8::104;73:26:73:47:0;:50::51;:26:::1;:16::68;:83::104:0;:107::108;:83:::1;:72::125;:8::127;76:27:76:48:0;:51::52;:27:::1;:16::67;:71::82:0;;:8::84:1;77:27:77:48:0;:51::52;:27:::1;:16::67;:77::93:0;;:104::108;;:96::109:1;:77;:8::112;80:27:80:48:0;:51::52;:27:::1;:16::67;:71::83:0;;:8::85:1;81:27:81:48:0;:51::52;:27:::1;:16::67;:77::93:0;;:104::108;;:96::109:1;:77;:8::112;84:26:84:27:0;85:8:94:49;86:23:86:34;:36::57;:59::80;:83::84;:59:::1;:16::85;:15:92:13:0;87:30:87:41;:19::56:1;:60::62:0;:19:::1;::91:17:0;89:39:89:50;:28::65:1;:75::77:0;:28::78:1;;:82::93:0;;:28:::1;;:20::95;90:39:90:50:0;:28::65:1;:75::77:0;:28::78:1;;:82::94:0;;:28:::1;;:20::96;87:64:91:17;86:87:92:13;93:26:93:37:0;:::41:1;:12::42;94:16:94:27:0;:30::47;85:8::49:1;;33:4:95:5;;;",
|
|
33
|
+
"logs": [],
|
|
34
|
+
"requires": [
|
|
35
|
+
{
|
|
36
|
+
"ip": 7,
|
|
37
|
+
"line": 35
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"ip": 12,
|
|
41
|
+
"line": 36
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"ip": 17,
|
|
45
|
+
"line": 37
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"ip": 28,
|
|
49
|
+
"line": 43
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"ip": 36,
|
|
53
|
+
"line": 47
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"ip": 57,
|
|
57
|
+
"line": 55
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"ip": 74,
|
|
61
|
+
"line": 59
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"ip": 121,
|
|
65
|
+
"line": 67
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"ip": 130,
|
|
69
|
+
"line": 69
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"ip": 141,
|
|
73
|
+
"line": 72
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"ip": 150,
|
|
77
|
+
"line": 73
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"ip": 157,
|
|
81
|
+
"line": 76
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"ip": 168,
|
|
85
|
+
"line": 77
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"ip": 175,
|
|
89
|
+
"line": 80
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"ip": 186,
|
|
93
|
+
"line": 81
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"ip": 210,
|
|
97
|
+
"line": 89
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"ip": 220,
|
|
101
|
+
"line": 90
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"compiler": {
|
|
106
|
+
"name": "cashc",
|
|
107
|
+
"version": "0.13.0-next.6",
|
|
108
|
+
"options": {
|
|
109
|
+
"enforceFunctionParameterTypes": true
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"updatedAt": "2026-05-06T19:09:27.004Z"
|
|
113
|
+
}
|
package/constants.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const BitcoinCategory = '0'.repeat(32 * 2);
|
package/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import PublicFundTransactionBuilder from './PublicFundTransactionBuilder.js';
|
|
2
|
+
import FundTokenTransactionBuilder from './FundTokenTransactionBuilder.js';
|
|
3
|
+
import { BitcoinCategory } from './constants.js';
|
|
4
|
+
import { getFundHex, getFundBin, decodeFund, getBestFee, hashFund, decodeFee, encodeFee, getAvailableFees } from './utils.js';
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
PublicFundTransactionBuilder,
|
|
8
|
+
FundTokenTransactionBuilder,
|
|
9
|
+
BitcoinCategory,
|
|
10
|
+
getFundHex,
|
|
11
|
+
getFundBin,
|
|
12
|
+
decodeFund,
|
|
13
|
+
getBestFee,
|
|
14
|
+
hashFund,
|
|
15
|
+
decodeFee,
|
|
16
|
+
encodeFee,
|
|
17
|
+
getAvailableFees,
|
|
18
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fundtokens/builders",
|
|
3
|
+
"version": "0.1.0-rc10",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@bitauth/libauth": "3.1.0-next.8",
|
|
8
|
+
"cashc": "0.13.0",
|
|
9
|
+
"cashscript": "0.13.0"
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {},
|
|
12
|
+
"author": "Fun(d)Tokens",
|
|
13
|
+
"description": "Transaction builders to create and interact with FundTokens.",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"BitcoinCash",
|
|
16
|
+
"Bitcoin Cash",
|
|
17
|
+
"CashTokens",
|
|
18
|
+
"DeFi",
|
|
19
|
+
"FundTokens"
|
|
20
|
+
]
|
|
21
|
+
}
|