@lifestonelabs/tokensales 1.0.6 → 1.0.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
  ______________________________________________________________
3
+ ## [1.0.8] - 2026-02-10
4
+ ### Changed
5
+ - `burn` added additional index check in contract to ensure user-provided MintingNFT must be input0
6
+ ______________________________________________________________
7
+ ## [1.0.7] - 2026-02-10
8
+ ### Changed
9
+ - `buyNFT` fixed change fee calculation in contract to take ticket price into account
10
+ ______________________________________________________________
3
11
  ## [1.0.6] - 2026-02-09
4
12
  ### Changed
5
13
  - `buyNFT` & `burn` made ticketMasterUtxo param optional. They now fetch the correct TokenSale UTXO from the contract if one is not provided.
package/dist/config.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export declare const DEFAULT_CONTRACT_ADDRESSES: {
2
- readonly contract: "bitcoincash:pdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2m4afvzlt";
3
- readonly token: "bitcoincash:rdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2fxpg4rxq";
2
+ readonly contract: "bitcoincash:pwmw72w62fyh5fp6wwnsz9w7mehrsef3frxdh2h6ynmlvc4ch3dnwzutlweuk";
3
+ readonly token: "bitcoincash:rwmw72w62fyh5fp6wwnsz9w7mehrsef3frxdh2h6ynmlvc4ch3dnws0h7hc9a";
4
4
  };
5
5
  /**
6
6
  * Get contract address
@@ -1,5 +1,5 @@
1
- export declare const AddressTicketMaster = "bitcoincash:pdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2m4afvzlt";
2
- export declare const AddressTicketMasterToken = "bitcoincash:rdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2fxpg4rxq";
1
+ export declare const AddressTicketMaster = "bitcoincash:pwmw72w62fyh5fp6wwnsz9w7mehrsef3frxdh2h6ynmlvc4ch3dnwzutlweuk";
2
+ export declare const AddressTicketMasterToken = "bitcoincash:rwmw72w62fyh5fp6wwnsz9w7mehrsef3frxdh2h6ynmlvc4ch3dnws0h7hc9a";
3
3
  export declare const TICKET_LEVEL_DESCRIPTIONS: {
4
4
  '01': {
5
5
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/constants/values.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,8EAA8E,CAAC;AAC/G,eAAO,MAAM,wBAAwB,8EAA8E,CAAC;AAIpH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;CAarC,CAAC"}
1
+ {"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/constants/values.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,mBAAmB,8EAA8E,CAAC;AAC/G,eAAO,MAAM,wBAAwB,8EAA8E,CAAC;AAGpH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;CAarC,CAAC"}
package/dist/index.esm.js CHANGED
@@ -215,9 +215,15 @@ function toLittleEndianHexString(number, byteCount) {
215
215
  // TokenSales_old1 contract addresses
216
216
  //export const AddressTicketMaster = 'bitcoincash:pvh0yat7d2r9nf228fpns3mypydvstq9arftt9qlmma42xeq2eryszkdd99zq'; //address hash: 2ef2757e6a8659a54a3a43384764091ac82c05e8d2b5941fdefb551b20564648
217
217
  //export const AddressTicketMasterToken = 'bitcoincash:rvh0yat7d2r9nf228fpns3mypydvstq9arftt9qlmma42xeq2eryss93vuymt';
218
- // TokenSales contract addresses | simplified change fee calculation in purchaseNFT()
219
- const AddressTicketMaster = 'bitcoincash:pdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2m4afvzlt'; //address hash: 76bebd71fef3c48ef2fec86b1a24ceaa7fb06f3e1aed923ac8176955c20f5085
220
- const AddressTicketMasterToken = 'bitcoincash:rdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2fxpg4rxq';
218
+ // TokenSales_old2 contract addresses | simplified change fee calculation in purchaseNFT()
219
+ //export const AddressTicketMaster = 'bitcoincash:pdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2m4afvzlt'; //address hash: 76bebd71fef3c48ef2fec86b1a24ceaa7fb06f3e1aed923ac8176955c20f5085
220
+ //export const AddressTicketMasterToken = 'bitcoincash:rdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2fxpg4rxq';
221
+ // TokenSales_old3 contract addresses | fixed change fee calculation in purchaseNFT()
222
+ //export const AddressTicketMaster = 'bitcoincash:pdllrevwdxsngc2f6cqqhml2288580c2al8lqtq4cg9ywupyqqh5vz3syd0y9'; //address hash: 7ff1e58e69a1346149d6000befea51cf43bf0aefcff02c15c20a477024002f46
223
+ //export const AddressTicketMasterToken = 'bitcoincash:rdllrevwdxsngc2f6cqqhml2288580c2al8lqtq4cg9ywupyqqh5vszv95waw';
224
+ // TokenSales contract addresses | restricted burnTokenSale() so user-provided utxo must be input0
225
+ const AddressTicketMaster = 'bitcoincash:pwmw72w62fyh5fp6wwnsz9w7mehrsef3frxdh2h6ynmlvc4ch3dnwzutlweuk'; //address hash: b6ef29da52497a243a73a70115dede6e38653148ccdbaafa24f7f662b8bc5b37
226
+ const AddressTicketMasterToken = 'bitcoincash:rwmw72w62fyh5fp6wwnsz9w7mehrsef3frxdh2h6ynmlvc4ch3dnws0h7hc9a';
221
227
  // Ticket Level Descriptions
222
228
  const TICKET_LEVEL_DESCRIPTIONS = {
223
229
  '01': {
@@ -312,11 +318,11 @@ var abi = [
312
318
  ]
313
319
  }
314
320
  ];
315
- var bytecode = "OP_DUP OP_0 OP_NUMEQUAL OP_IF OP_0 OP_UTXOBYTECODE OP_1 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_UTXOTOKENCATEGORY 20 OP_SPLIT OP_2 OP_EQUALVERIFY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT 13 OP_SPLIT OP_DROP OP_15 OP_SPLIT OP_NIP OP_TXLOCKTIME OP_SWAP OP_BIN2NUM OP_LESSTHAN OP_VERIFY OP_TXINPUTCOUNT OP_3 OP_NUMEQUALVERIFY OP_TXOUTPUTCOUNT OP_4 OP_LESSTHANOREQUAL OP_VERIFY OP_0 OP_0 OP_3 OP_PICK OP_1 OP_EQUAL OP_IF OP_0 OP_UTXOTOKENCOMMITMENT OP_5 OP_SPLIT OP_DROP OP_1 OP_UTXOTOKENCOMMITMENT OP_1 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_NIP OP_ELSE OP_3 OP_PICK OP_2 OP_EQUAL OP_IF OP_0 OP_UTXOTOKENCOMMITMENT OP_10 OP_SPLIT OP_DROP OP_5 OP_SPLIT OP_NIP OP_DUP 000000000000 OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_SWAP OP_1 OP_UTXOTOKENCOMMITMENT OP_2 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DROP OP_ELSE OP_3 OP_PICK OP_3 OP_EQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT OP_15 OP_SPLIT OP_DROP OP_10 OP_SPLIT OP_NIP OP_DUP 000000000000 OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_SWAP OP_1 OP_UTXOTOKENCOMMITMENT OP_3 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DROP OP_ENDIF OP_ENDIF OP_1 OP_OUTPUTTOKENCOMMITMENT OP_ROT OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_2 OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENAMOUNT OP_1 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_1 OP_OUTPUTVALUE OP_1 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_2 OP_UTXOTOKENCATEGORY OP_0 OP_EQUAL OP_2 OP_UTXOTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUAL OP_DUP OP_ROT OP_BOOLOR OP_VERIFY OP_DUP OP_IF OP_TXOUTPUTCOUNT OP_4 OP_NUMEQUALVERIFY OP_ENDIF OP_IF e803 OP_NIP OP_ENDIF OP_0 OP_UTXOTOKENCOMMITMENT 27 OP_SPLIT OP_DROP 13 OP_SPLIT OP_NIP 76a914 OP_SWAP OP_CAT 88ac OP_CAT OP_2 OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_2 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_2 OP_OUTPUTVALUE OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_0 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_2 OP_UTXOVALUE 1027 OP_SUB OP_0 OP_MAX OP_DUP e803 OP_GREATERTHAN OP_IF OP_3 OP_OUTPUTBYTECODE OP_2 OP_UTXOBYTECODE OP_EQUALVERIFY OP_3 OP_OUTPUTTOKENCATEGORY OP_2 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_3 OP_OUTPUTTOKENCOMMITMENT OP_2 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_3 OP_OUTPUTVALUE OP_OVER OP_GREATERTHANOREQUAL OP_VERIFY OP_ENDIF OP_2DROP OP_DROP OP_1 OP_ELSE OP_DUP OP_1 OP_NUMEQUAL OP_IF OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY OP_1 OP_UTXOTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_TXINPUTCOUNT OP_2 OP_NUMEQUALVERIFY OP_TXOUTPUTCOUNT OP_2 OP_NUMEQUALVERIFY OP_OVER OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_2 OP_PICK OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_3 OP_PICK OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_4 OP_PICK OP_SIZE OP_NIP OP_4 OP_NUMEQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT 27 OP_SPLIT OP_DROP 13 OP_SPLIT OP_NIP OP_0 OP_OUTPUTTOKENCOMMITMENT OP_3 OP_ROLL OP_4 OP_ROLL OP_CAT OP_4 OP_ROLL OP_CAT OP_4 OP_ROLL OP_CAT OP_ROT OP_CAT OP_EQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_1 OP_OUTPUTTOKENCOMMITMENT OP_1 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_1 OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENAMOUNT OP_1 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_1 OP_OUTPUTVALUE OP_1 OP_UTXOVALUE 1027 OP_SUB OP_GREATERTHANOREQUAL OP_NIP OP_ELSE OP_DUP OP_2 OP_NUMEQUAL OP_IF OP_1 OP_UTXOTOKENCATEGORY 20 OP_SPLIT OP_2 OP_EQUALVERIFY OP_0 OP_UTXOTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_1ADD OP_TXINPUTCOUNT OP_OVER OP_GREATERTHAN OP_IF OP_DUP OP_UTXOTOKENCATEGORY OP_2 OP_PICK OP_EQUALVERIFY OP_ENDIF OP_0 OP_OUTPUTTOKENCOMMITMENT OP_0 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE 1027 OP_SUB OP_GREATERTHANOREQUAL OP_VERIFY OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUAL OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_NUMEQUALVERIFY cc9b01 OP_CHECKSEQUENCEVERIFY OP_DROP OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUAL OP_ENDIF OP_ENDIF OP_ENDIF";
316
- var source = "pragma cashscript ^0.12.0;\r\n\r\ncontract TokenSales() {\r\n// Single-contract NFT Marketplace on Bitcoin Cash\r\n// \r\n// 1. Sale owner creates a `TokenSale` MintingNFT of the same category as the NFTs to be sold. The TokenSale MintingNFT must have its commitment setup as:\r\n//\r\n /* --- State `TokenSale` Minting NFT ---\r\n bytes5 priceType1\r\n bytes5 priceType2\r\n bytes5 priceType3\r\n bytes4 endSale \r\n bytes20 adminPubKeyHash\r\n */\r\n//\r\n// 2. Sale owner sends the immutableNFTs to be sold of the same categoory to this contract. (mutableNFT's will be stuck in the contract until they are reclaim()'d)\r\n// 3. Users can purchase any NFT and can choose what `type` the NFT will be, paying the appropriate price.\r\n// Purchases require the sale is active (endSale block has not yet been reached).\r\n// Up to 3 NFT types with different prices can be set. If a types price is set to 0 the type will not be available for purchase.\r\n// 4. Each sales BCH price is sent to the adminPubKeyHash address.\r\n// 5. Admin can perform the following actions at any time:\r\n// - Change the price of the three NFT types.\r\n// - Change the endSale block number, including stopping a currently-active sale, re-starting a stopped sale, and extending a sale.\r\n// - Burn the TokenSaleNFT ('the sale') and any remaining NFTs of the same category.\r\n// - Purchase a NFT for 1000sats by providing another MintingNFT of the same category. (so adminsPubKeyHash address will have an entry for all sold NFTs, even those that admin took for 'free')\r\n//\r\n// Additionally, a reclaim() function is provided to reclaim the satoshis from UTXOs on this contract that have been abandoned for 2 years.\r\n// This is a workaround for any stray UTXOs that are sent to or left on the contract (e.g. if NFT's are not included in the burnTokenSale() function)\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n ////////////////////////////////// Purchase a NFT ///////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// User purchases a NFT. Must include a MintingNFT of the same category (`TokenSale`). \r\n// Updates NFT commitment with the type of NFT purchased. \r\n// Enforces any change back to user.\r\n// Admin can provide another MintingNFT (with BCH on it) of the same category instead of a BCH UTXO to buy an NFT of any type for free.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// 1 NFT [NFT] (from TokenSale contract)\r\n// [2 userUTXO [BCH] (from user)\r\n// OR] adminUTXO [NFT]-Minting (from admin)\r\n//outputs:\r\n// 0 TokenSale [NFT]-Minting (to TokenSale contract)\r\n// 1 NFT [NFT] (to user)\r\n// 2 payment [BCH] (to adminPkh)\r\n// [3 {optional} change [BCH] (to user)\r\n// OR] adminUTXO [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function purchaseNFT(byte nftType) {\r\n // verify input0 is the MintingNFT from this contract. (also forces TokenSaleNFT as input0 rather than an adminNFT)\r\n require(tx.inputs[0].lockingBytecode == tx.inputs[1].lockingBytecode);\r\n bytes tokenSaleCategoryID, bytes tokenSaleCapability = tx.inputs[0].tokenCategory.split(32);\r\n require(tokenSaleCapability == 0x02);\r\n\r\n // verify NFT is for this tokenSaleCategoryID\r\n require(tx.inputs[1].tokenCategory == tokenSaleCategoryID);\r\n\r\n // require sale has not ended\r\n bytes endSale = tx.inputs[0].nftCommitment.slice(15,19);\r\n require(tx.locktime < int(endSale));\r\n\r\n // verify tx limits\r\n require(tx.inputs.length == 3);\r\n require(tx.outputs.length <= 4);\r\n\r\n bytes newNFTCommitment = 0x;\r\n int nftPrice = 0;\r\n // buy NFT based on type \r\n if (nftType == 0x01) {\r\n bytes5 priceType1 = tx.inputs[0].nftCommitment.split(5)[0];\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x01;\r\n nftPrice = int(priceType1);\r\n } else if (nftType == 0x02) {\r\n bytes5 priceType2 = tx.inputs[0].nftCommitment.slice(5,10);\r\n require(priceType2 != 0x000000000000);\r\n nftPrice = int(priceType2);\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x02;\r\n } else {\r\n require(nftType == 0x03);\r\n bytes5 priceType3 = tx.inputs[0].nftCommitment.slice(10,15);\r\n require(priceType3 != 0x000000000000);\r\n nftPrice = int(priceType3);\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x03;\r\n }\r\n\r\n // send NFT to user with updated type\r\n require(tx.outputs[1].nftCommitment == newNFTCommitment);\r\n require(tx.outputs[1].lockingBytecode == tx.inputs[2].lockingBytecode);\r\n require(tx.outputs[1].tokenCategory == tx.inputs[1].tokenCategory);\r\n require(tx.outputs[1].tokenAmount == tx.inputs[1].tokenAmount);\r\n require(tx.outputs[1].value == tx.inputs[1].value);\r\n\r\n // verify user providing either pure BCH or adminNFT\r\n bool isPureBCH = tx.inputs[2].tokenCategory == 0x;\r\n bool isAdmin = tx.inputs[2].tokenCategory == tx.inputs[0].tokenCategory;\r\n require(isAdmin || isPureBCH);\r\n\r\n // if admin, set nftPrice to 0 and prevent accidental burning of adminNFT\r\n if (isAdmin) require(tx.outputs.length == 4);\r\n if (isAdmin) nftPrice = 1000;\r\n \r\n // send payment to adminPkh\r\n bytes20 adminPkh = tx.inputs[0].nftCommitment.slice(19,39);\r\n bytes adminAddress = new LockingBytecodeP2PKH(adminPkh); \r\n require(tx.outputs[2].lockingBytecode == adminAddress);\r\n require(tx.outputs[2].tokenCategory == 0x);\r\n require(tx.outputs[2].value == nftPrice);\r\n\r\n // recreate TokenSale MintingNFT\r\n require(tx.outputs[0].value == tx.inputs[0].value);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount); \r\n require(tx.outputs[0].nftCommitment == tx.inputs[0].nftCommitment);\r\n\r\n // determine how much change exists after reserving up to 10_000 sats for miner fee\r\n int change = max((tx.inputs[2].value - 10000), 0);\r\n // return change to user\r\n if (change > 1000) {\r\n require(tx.outputs[3].lockingBytecode == tx.inputs[2].lockingBytecode);\r\n require(tx.outputs[3].tokenCategory == tx.inputs[2].tokenCategory);\r\n require(tx.outputs[3].nftCommitment == tx.inputs[2].nftCommitment);\r\n require(tx.outputs[3].value >= change);\r\n }\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n ////////////////////////////// Modify TokenSale NFT //////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Admin can change the `TokenSale` NFT type prices and endSale block number.\r\n// Requires 2000sats extra on the adminNFT to cover tx fee.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// 1 adminNFT [NFT]-Minting (from admin)\r\n//outputs:\r\n// 0 TokenSale [NFT]-Minting (to TokenSale contract) \r\n// 1 adminNFT [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n//parameters:\r\n// priceType1: the price of a type1 NFT (in satoshis)\r\n// priceType2: the price of a type2 NFT (in satoshis)\r\n// priceType3: the price of a type3 NFT (in satoshis)\r\n// endSale: the block number to end sale at\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function modifyTokenSale(bytes5 priceType1, bytes5 priceType2, bytes5 priceType3, bytes4 endSale) {\r\n // verify input0 is from this contract\r\n require(this.activeInputIndex == 0);\r\n\r\n // verify adminNFT is for this TokenSaleCategoryID\r\n require(tx.inputs[1].tokenCategory == tx.inputs[0].tokenCategory);\r\n\r\n // verify tx limits\r\n require(tx.inputs.length == 2);\r\n require(tx.outputs.length == 2); \r\n\r\n // verify parameters are correct lengths\r\n require(priceType1.length == 5);\r\n require(priceType2.length == 5);\r\n require(priceType3.length == 5);\r\n require(endSale.length == 4);\r\n\r\n // recreate TokenSale. Implicitly enforces that input0 is not an immutableNFT\r\n bytes20 adminPkh = tx.inputs[0].nftCommitment.slice(19,39);\r\n require(tx.outputs[0].nftCommitment == priceType1 + priceType2 + priceType3 + endSale + adminPkh);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount);\r\n require(tx.outputs[0].value == tx.inputs[0].value);\r\n\r\n // recreate adminNFT\r\n require(tx.outputs[1].nftCommitment == tx.inputs[1].nftCommitment);\r\n require(tx.outputs[1].lockingBytecode == tx.inputs[1].lockingBytecode);\r\n require(tx.outputs[1].tokenCategory == tx.inputs[1].tokenCategory);\r\n require(tx.outputs[1].tokenAmount == tx.inputs[1].tokenAmount);\r\n require(tx.outputs[1].value >= tx.inputs[1].value - 10000);\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n /////////////////////////////// Burn TokenSale ///////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Admin can burn the `TokenSale` NFT and any remaining NFTs of this category.\r\n// No other inputs besides NFTs of this category are permitted for inputs2+.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 adminNFT [NFT]-Minting (from admin)\r\n// 1 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// N NFTs [NFT] (from TokenSale contract)\r\n//outputs:\r\n// 0 adminNFT [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function burnTokenSale() {\r\n // verify input1 is a MintingNFT\r\n bytes tokenSaleCategoryID, bytes tokenSaleCapability = tx.inputs[1].tokenCategory.split(32);\r\n require(tokenSaleCapability == 0x02);\r\n\r\n // verify adminNFT is for this TokenSale\r\n require(tx.inputs[0].tokenCategory == tx.inputs[1].tokenCategory);\r\n\r\n //require next input is a NFT of this category\r\n int nextIndex = this.activeInputIndex + 1;\r\n if (tx.inputs.length > nextIndex) {\r\n require(tx.inputs[nextIndex].tokenCategory == tokenSaleCategoryID);\r\n }\r\n\r\n // recreate adminNFT\r\n require(tx.outputs[0].nftCommitment == tx.inputs[0].nftCommitment);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount);\r\n require(tx.outputs[0].value >= tx.inputs[0].value - 10000);\r\n\r\n // verify tx limits\r\n require(tx.outputs.length == 1); \r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n //////////////////////////// Reclaim Expired Inputs /////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Anyone can reclaim the satoshis from utxos on this contract that have been abandoned for 2 years.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0+ UTXO [Any] (from TokenSale contract)\r\n//outputs:\r\n// 0 UTXO [BCH] (to anyone)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function reclaim() {\r\n require(this.age >= 105420);\r\n\r\n // verify tx limits\r\n require(tx.outputs.length == 1); \r\n\r\n // enforce output\r\n require(tx.outputs[0].tokenCategory == 0x);\r\n\r\n }\r\n}";
321
+ var bytecode = "OP_DUP OP_0 OP_NUMEQUAL OP_IF OP_0 OP_UTXOBYTECODE OP_1 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_UTXOTOKENCATEGORY 20 OP_SPLIT OP_2 OP_EQUALVERIFY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT 13 OP_SPLIT OP_DROP OP_15 OP_SPLIT OP_NIP OP_TXLOCKTIME OP_SWAP OP_BIN2NUM OP_LESSTHAN OP_VERIFY OP_TXINPUTCOUNT OP_3 OP_NUMEQUALVERIFY OP_TXOUTPUTCOUNT OP_4 OP_LESSTHANOREQUAL OP_VERIFY OP_0 OP_0 OP_3 OP_PICK OP_1 OP_EQUAL OP_IF OP_0 OP_UTXOTOKENCOMMITMENT OP_5 OP_SPLIT OP_DROP OP_1 OP_UTXOTOKENCOMMITMENT OP_1 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_NIP OP_ELSE OP_3 OP_PICK OP_2 OP_EQUAL OP_IF OP_0 OP_UTXOTOKENCOMMITMENT OP_10 OP_SPLIT OP_DROP OP_5 OP_SPLIT OP_NIP OP_DUP 000000000000 OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_SWAP OP_1 OP_UTXOTOKENCOMMITMENT OP_2 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DROP OP_ELSE OP_3 OP_PICK OP_3 OP_EQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT OP_15 OP_SPLIT OP_DROP OP_10 OP_SPLIT OP_NIP OP_DUP 000000000000 OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_SWAP OP_1 OP_UTXOTOKENCOMMITMENT OP_3 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DROP OP_ENDIF OP_ENDIF OP_1 OP_OUTPUTTOKENCOMMITMENT OP_ROT OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_2 OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENAMOUNT OP_1 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_1 OP_OUTPUTVALUE OP_1 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_2 OP_UTXOTOKENCATEGORY OP_0 OP_EQUAL OP_2 OP_UTXOTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUAL OP_DUP OP_ROT OP_BOOLOR OP_VERIFY OP_DUP OP_IF OP_TXOUTPUTCOUNT OP_4 OP_NUMEQUALVERIFY OP_ENDIF OP_IF e803 OP_NIP OP_ENDIF OP_0 OP_UTXOTOKENCOMMITMENT 27 OP_SPLIT OP_DROP 13 OP_SPLIT OP_NIP 76a914 OP_SWAP OP_CAT 88ac OP_CAT OP_2 OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_2 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_2 OP_OUTPUTVALUE OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_0 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_2 OP_UTXOVALUE OP_2 OP_OUTPUTVALUE OP_SUB 1027 OP_SUB OP_0 OP_MAX OP_DUP e803 OP_GREATERTHAN OP_IF OP_3 OP_OUTPUTBYTECODE OP_2 OP_UTXOBYTECODE OP_EQUALVERIFY OP_3 OP_OUTPUTTOKENCATEGORY OP_2 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_3 OP_OUTPUTTOKENCOMMITMENT OP_2 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_3 OP_OUTPUTVALUE OP_OVER OP_GREATERTHANOREQUAL OP_VERIFY OP_ENDIF OP_2DROP OP_DROP OP_1 OP_ELSE OP_DUP OP_1 OP_NUMEQUAL OP_IF OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY OP_1 OP_UTXOTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_TXINPUTCOUNT OP_2 OP_NUMEQUALVERIFY OP_TXOUTPUTCOUNT OP_2 OP_NUMEQUALVERIFY OP_OVER OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_2 OP_PICK OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_3 OP_PICK OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_4 OP_PICK OP_SIZE OP_NIP OP_4 OP_NUMEQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT 27 OP_SPLIT OP_DROP 13 OP_SPLIT OP_NIP OP_0 OP_OUTPUTTOKENCOMMITMENT OP_3 OP_ROLL OP_4 OP_ROLL OP_CAT OP_4 OP_ROLL OP_CAT OP_4 OP_ROLL OP_CAT OP_ROT OP_CAT OP_EQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_1 OP_OUTPUTTOKENCOMMITMENT OP_1 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_1 OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENAMOUNT OP_1 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_1 OP_OUTPUTVALUE OP_1 OP_UTXOVALUE 1027 OP_SUB OP_GREATERTHANOREQUAL OP_NIP OP_ELSE OP_DUP OP_2 OP_NUMEQUAL OP_IF OP_1 OP_UTXOTOKENCATEGORY 20 OP_SPLIT OP_2 OP_EQUALVERIFY OP_0 OP_UTXOTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_0 OP_GREATERTHAN OP_VERIFY OP_INPUTINDEX OP_1ADD OP_TXINPUTCOUNT OP_OVER OP_GREATERTHAN OP_IF OP_DUP OP_UTXOTOKENCATEGORY OP_2 OP_PICK OP_EQUALVERIFY OP_ENDIF OP_0 OP_OUTPUTTOKENCOMMITMENT OP_0 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE 1027 OP_SUB OP_GREATERTHANOREQUAL OP_VERIFY OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUAL OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_NUMEQUALVERIFY cc9b01 OP_CHECKSEQUENCEVERIFY OP_DROP OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUAL OP_ENDIF OP_ENDIF OP_ENDIF";
322
+ var source = "pragma cashscript ^0.12.0;\r\n\r\ncontract TokenSales() {\r\n// Single-contract NFT Marketplace on Bitcoin Cash\r\n// \r\n// 1. Sale owner creates a `TokenSale` MintingNFT of the same category as the NFTs to be sold. The TokenSale MintingNFT must have its commitment setup as:\r\n//\r\n /* --- State `TokenSale` Minting NFT ---\r\n bytes5 priceType1\r\n bytes5 priceType2\r\n bytes5 priceType3\r\n bytes4 endSale \r\n bytes20 adminPubKeyHash\r\n */\r\n//\r\n// 2. Sale owner sends the immutableNFTs to be sold of the same categoory to this contract. (mutableNFT's will be stuck in the contract until they are reclaim()'d)\r\n// 3. Users can purchase any NFT and can choose what `type` the NFT will be, paying the appropriate price.\r\n// Purchases require the sale is active (endSale block has not yet been reached).\r\n// Up to 3 NFT types with different prices can be set. If a types price is set to 0 the type will not be available for purchase.\r\n// 4. Each sales BCH price is sent to the adminPubKeyHash address.\r\n// 5. Admin can perform the following actions at any time:\r\n// - Change the price of the three NFT types.\r\n// - Change the endSale block number, including stopping a currently-active sale, re-starting a stopped sale, and extending a sale.\r\n// - Burn the TokenSaleNFT ('the sale') and any remaining NFTs of the same category.\r\n// - Purchase a NFT for 1000sats by providing another MintingNFT of the same category. (so adminsPubKeyHash address will have an entry for all sold NFTs, even those that admin took for 'free')\r\n//\r\n// Additionally, a reclaim() function is provided to reclaim the satoshis from UTXOs on this contract that have been abandoned for 2 years.\r\n// This is a workaround for any stray UTXOs that are sent to or left on the contract (e.g. if NFT's are not included in the burnTokenSale() function)\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n ////////////////////////////////// Purchase a NFT ///////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// User purchases a NFT. Must include a MintingNFT of the same category (`TokenSale`). \r\n// Updates NFT commitment with the type of NFT purchased. \r\n// Enforces any change back to user.\r\n// Admin can provide another MintingNFT (with BCH on it) of the same category instead of a BCH UTXO to buy an NFT of any type for free.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// 1 NFT [NFT] (from TokenSale contract)\r\n// [2 userUTXO [BCH] (from user)\r\n// OR] adminUTXO [NFT]-Minting (from admin)\r\n//outputs:\r\n// 0 TokenSale [NFT]-Minting (to TokenSale contract)\r\n// 1 NFT [NFT] (to user)\r\n// 2 payment [BCH] (to adminPkh)\r\n// [3 {optional} change [BCH] (to user)\r\n// OR] adminUTXO [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function purchaseNFT(byte nftType) {\r\n // verify input0 is the MintingNFT from this contract. (also forces TokenSaleNFT as input0 rather than an adminNFT)\r\n require(tx.inputs[0].lockingBytecode == tx.inputs[1].lockingBytecode);\r\n bytes tokenSaleCategoryID, bytes tokenSaleCapability = tx.inputs[0].tokenCategory.split(32);\r\n require(tokenSaleCapability == 0x02);\r\n\r\n // verify NFT is for this tokenSaleCategoryID\r\n require(tx.inputs[1].tokenCategory == tokenSaleCategoryID);\r\n\r\n // require sale has not ended\r\n bytes endSale = tx.inputs[0].nftCommitment.slice(15,19);\r\n require(tx.locktime < int(endSale));\r\n\r\n // verify tx limits\r\n require(tx.inputs.length == 3);\r\n require(tx.outputs.length <= 4);\r\n\r\n bytes newNFTCommitment = 0x;\r\n int nftPrice = 0;\r\n // buy NFT based on type \r\n if (nftType == 0x01) {\r\n bytes5 priceType1 = tx.inputs[0].nftCommitment.split(5)[0];\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x01;\r\n nftPrice = int(priceType1);\r\n } else if (nftType == 0x02) {\r\n bytes5 priceType2 = tx.inputs[0].nftCommitment.slice(5,10);\r\n require(priceType2 != 0x000000000000);\r\n nftPrice = int(priceType2);\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x02;\r\n } else {\r\n require(nftType == 0x03);\r\n bytes5 priceType3 = tx.inputs[0].nftCommitment.slice(10,15);\r\n require(priceType3 != 0x000000000000);\r\n nftPrice = int(priceType3);\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x03;\r\n }\r\n\r\n // send NFT to user with updated type\r\n require(tx.outputs[1].nftCommitment == newNFTCommitment);\r\n require(tx.outputs[1].lockingBytecode == tx.inputs[2].lockingBytecode);\r\n require(tx.outputs[1].tokenCategory == tx.inputs[1].tokenCategory);\r\n require(tx.outputs[1].tokenAmount == tx.inputs[1].tokenAmount);\r\n require(tx.outputs[1].value == tx.inputs[1].value);\r\n\r\n // verify user providing either pure BCH or adminNFT\r\n bool isPureBCH = tx.inputs[2].tokenCategory == 0x;\r\n bool isAdmin = tx.inputs[2].tokenCategory == tx.inputs[0].tokenCategory;\r\n require(isAdmin || isPureBCH);\r\n\r\n // if admin, set nftPrice to 0 and prevent accidental burning of adminNFT\r\n if (isAdmin) require(tx.outputs.length == 4);\r\n if (isAdmin) nftPrice = 1000;\r\n \r\n // send payment to adminPkh\r\n bytes20 adminPkh = tx.inputs[0].nftCommitment.slice(19,39);\r\n bytes adminAddress = new LockingBytecodeP2PKH(adminPkh); \r\n require(tx.outputs[2].lockingBytecode == adminAddress);\r\n require(tx.outputs[2].tokenCategory == 0x);\r\n require(tx.outputs[2].value == nftPrice);\r\n\r\n // recreate TokenSale MintingNFT\r\n require(tx.outputs[0].value == tx.inputs[0].value);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount); \r\n require(tx.outputs[0].nftCommitment == tx.inputs[0].nftCommitment);\r\n\r\n // determine how much change exists after reserving up to 10_000 sats for miner fee\r\n int change = max((tx.inputs[2].value - tx.outputs[2].value - 10000), 0);\r\n // return change to user\r\n if (change > 1000) {\r\n require(tx.outputs[3].lockingBytecode == tx.inputs[2].lockingBytecode);\r\n require(tx.outputs[3].tokenCategory == tx.inputs[2].tokenCategory);\r\n require(tx.outputs[3].nftCommitment == tx.inputs[2].nftCommitment);\r\n require(tx.outputs[3].value >= change);\r\n }\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n ////////////////////////////// Modify TokenSale NFT //////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Admin can change the `TokenSale` NFT type prices and endSale block number.\r\n// Requires 2000sats extra on the adminNFT to cover tx fee.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// 1 adminNFT [NFT]-Minting (from admin)\r\n//outputs:\r\n// 0 TokenSale [NFT]-Minting (to TokenSale contract) \r\n// 1 adminNFT [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n//parameters:\r\n// priceType1: the price of a type1 NFT (in satoshis)\r\n// priceType2: the price of a type2 NFT (in satoshis)\r\n// priceType3: the price of a type3 NFT (in satoshis)\r\n// endSale: the block number to end sale at\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function modifyTokenSale(bytes5 priceType1, bytes5 priceType2, bytes5 priceType3, bytes4 endSale) {\r\n // verify input0 is from this contract\r\n require(this.activeInputIndex == 0);\r\n\r\n // verify adminNFT is for this TokenSaleCategoryID\r\n require(tx.inputs[1].tokenCategory == tx.inputs[0].tokenCategory);\r\n\r\n // verify tx limits\r\n require(tx.inputs.length == 2);\r\n require(tx.outputs.length == 2); \r\n\r\n // verify parameters are correct lengths\r\n require(priceType1.length == 5);\r\n require(priceType2.length == 5);\r\n require(priceType3.length == 5);\r\n require(endSale.length == 4);\r\n\r\n // recreate TokenSale. Implicitly enforces that input0 is not an immutableNFT\r\n bytes20 adminPkh = tx.inputs[0].nftCommitment.slice(19,39);\r\n require(tx.outputs[0].nftCommitment == priceType1 + priceType2 + priceType3 + endSale + adminPkh);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount);\r\n require(tx.outputs[0].value == tx.inputs[0].value);\r\n\r\n // recreate adminNFT\r\n require(tx.outputs[1].nftCommitment == tx.inputs[1].nftCommitment);\r\n require(tx.outputs[1].lockingBytecode == tx.inputs[1].lockingBytecode);\r\n require(tx.outputs[1].tokenCategory == tx.inputs[1].tokenCategory);\r\n require(tx.outputs[1].tokenAmount == tx.inputs[1].tokenAmount);\r\n require(tx.outputs[1].value >= tx.inputs[1].value - 10000);\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n /////////////////////////////// Burn TokenSale ///////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Admin can burn the `TokenSale` NFT and any remaining NFTs of this category.\r\n// No other inputs besides NFTs of this category are permitted for inputs2+.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 adminNFT [NFT]-Minting (from admin)\r\n// 1 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// N NFTs [NFT] (from TokenSale contract)\r\n//outputs:\r\n// 0 adminNFT [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function burnTokenSale() {\r\n // verify input1 is a MintingNFT\r\n bytes tokenSaleCategoryID, bytes tokenSaleCapability = tx.inputs[1].tokenCategory.split(32);\r\n require(tokenSaleCapability == 0x02);\r\n\r\n // verify adminNFT is for this TokenSale\r\n require(tx.inputs[0].tokenCategory == tx.inputs[1].tokenCategory);\r\n\r\n //require TokenSale is not input0\r\n require(this.activeInputIndex > 0);\r\n\r\n //require next input is a NFT of this category\r\n int nextIndex = this.activeInputIndex + 1;\r\n if (tx.inputs.length > nextIndex) {\r\n require(tx.inputs[nextIndex].tokenCategory == tokenSaleCategoryID);\r\n }\r\n\r\n // recreate adminNFT\r\n require(tx.outputs[0].nftCommitment == tx.inputs[0].nftCommitment);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount);\r\n require(tx.outputs[0].value >= tx.inputs[0].value - 10000);\r\n\r\n // verify tx limits\r\n require(tx.outputs.length == 1); \r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n //////////////////////////// Reclaim Expired Inputs /////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Anyone can reclaim the satoshis from utxos on this contract that have been abandoned for 2 years.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0+ UTXO [Any] (from TokenSale contract)\r\n//outputs:\r\n// 0 UTXO [BCH] (to anyone)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function reclaim() {\r\n require(this.age >= 105420);\r\n\r\n // verify tx limits\r\n require(tx.outputs.length == 1); \r\n\r\n // enforce output\r\n require(tx.outputs[0].tokenCategory == 0x);\r\n\r\n }\r\n}";
317
323
  var debug = {
318
- bytecode: "76009c6300c751c78800ce01207f528851ce8800cf01137f755f7f77c57c819f69c3539dc454a1690000537951876300cf557f7551cf517e537a757c6b7c6c76817b757767537952876300cf5a7f75557f77760600000000000087916976817b757c51cf527e537a757c6b7c6c75675379538800cf5f7f755a7f77760600000000000087916976817b757c51cf537e537a757c6b7c6c75686851d27b8851cd52c78851d151ce8851d351d09d51cc51c69d52ce008752ce00ce87767b9b697663c4549d686302e803776800cf01277f7501137f770376a9147c7e0288ac7e52cd8852d1008852cc9d00cc00c69d00cd00c78800d100ce8800d300d09d00d200cf8852c60210279400a47602e803a06353cd52c78853d152ce8853d252cf8853cc78a269686d75516776519c63c0009d51ce00ce88c3529dc4529d788277559d52798277559d53798277559d54798277549d00cf01277f7501137f7700d2537a547a7e547a7e547a7e7b7e8800cd00c78800d100ce8800d300d09d00cc00c69d51d251cf8851cd51c78851d151ce8851d351d09d51cc51c602102794a2776776529c6351ce01207f528800ce51ce88c08bc378a06376ce5279886800d200cf8800cd00c78800d100ce8800d300d09d00cc00c602102794a269c4519c77777767539d03cc9b01b275c4519d00d10087686868",
319
- sourceMap: "50:4:126:4;;;;52:26:52:27;:16::44:1;:58::59:0;:48::76:1;:8::78;53:73:53:74:0;:63::89:1;:96::98:0;:63::99:1;54:39:54:43:0;:8::45:1;57:26:57:27:0;:16::42:1;:8::67;60:34:60:35:0;:24::50:1;:60::62:0;:24::63:1;;:57::59:0;:24::63:1;;61:16:61:27:0;:34::41;:30::42:1;:16;:8::44;64:16:64:32:0;:36::37;:8::39:1;65:16:65:33:0;:37::38;:16:::1;:8::40;67:33:67:35:0;68:23:68:24;70:12:70:19;;:23::27;:12:::1;:29:74:9:0;71:42:71:43;:32::58:1;:65::66:0;:32::67:1;:::70;72:41:72:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;73:27:73:37:0;:23::38:1;:12::39;;70:29:74:9;74:15:85::0;:19:74:26;;:30::34;:19:::1;:36:79:9:0;75:42:75:43;:32::58:1;:67::69:0;:32::70:1;;:65::66:0;:32::70:1;;76:20:76:30:0;:34::48;:20:::1;;:12::50;77:27:77:37:0;:23::38:1;:12::39;;;78:41:78:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;74:36:79:9;79:15:85::0;80:20:80:27;;:31::35;:12::37:1;81:42:81:43:0;:32::58:1;:68::70:0;:32::71:1;;:65::67:0;:32::71:1;;82:20:82:30:0;:34::48;:20:::1;;:12::50;83:27:83:37:0;:23::38:1;:12::39;;;84:41:84:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;79:15:85:9;;74;88:27:88:28:0;:16::43:1;:47::63:0;:8::65:1;89:27:89:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;90:27:90:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;91:27:91:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;92:27:92:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;95:35:95:36:0;:25::51:1;:55::57:0;:25:::1;96:33:96:34:0;:23::49:1;:63::64:0;:53::79:1;:23;97:16:97:23:0;:27::36;:16:::1;:8::38;100:12:100:19:0;:21::53;:29::46;:50::51;:21::53:1;;101::101:37:0;:32::36;:21::37:1;;104:37:104:38:0;:27::53:1;:63::65:0;:27::66:1;;:60::62:0;:27::66:1;;105:29:105:63:0;:54::62;:29::63:1;;;106:27:106:28:0;:16::45:1;:8::63;107:27:107:28:0;:16::43:1;:47::49:0;:8::51:1;108:27:108:28:0;:16::35:1;:8::49;111:27:111:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;112:27:112:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;113:27:113:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;114:27:114:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;115:27:115:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;118:36:118:37:0;:26::44:1;:47::52:0;:26:::1;:55::56:0;:21::57:1;120:12:120:18:0;:21::25;:12:::1;:27:125:9:0;121:31:121:32;:20::49:1;:63::64:0;:53::81:1;:12::83;122:31:122:32:0;:20::47:1;:61::62:0;:51::77:1;:12::79;123:31:123:32:0;:20::47:1;:61::62:0;:51::77:1;:12::79;124:31:124:32:0;:20::39:1;:43::49:0;:20:::1;:12::51;120:27:125:9;50:4:126:4;;;;147::178:5:0;;;;149:16:149:37;:41::42;:8::44:1;152:26:152:27:0;:16::42:1;:56::57:0;:46::72:1;:8::74;155:16:155:32:0;:36::37;:8::39:1;156:16:156:33:0;:37::38;:8::40:1;159:16:159:26:0;:::33:1;;:37::38:0;:8::40:1;160:16:160:26:0;;:::33:1;;:37::38:0;:8::40:1;161:16:161:26:0;;:::33:1;;:37::38:0;:8::40:1;162:16:162:23:0;;:::30:1;;:34::35:0;:8::37:1;165:37:165:38:0;:27::53:1;:63::65:0;:27::66:1;;:60::62:0;:27::66:1;;166::166:28:0;:16::43:1;:47::57:0;;:60::70;;:47:::1;:73::83:0;;:47:::1;:86::93:0;;:47:::1;:96::104:0;:47:::1;:8::106;167:27:167:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;168:27:168:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;169:27:169:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;170:27:170:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;173:27:173:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;174:27:174:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;175:27:175:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;176:27:176:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;177:27:177:28:0;:16::35:1;:49::50:0;:39::57:1;:60::65:0;:39:::1;:8::67;147:4:178:5;;193::216::0;;;;195:73:195:74;:63::89:1;:96::98:0;:63::99:1;196:39:196:43:0;:8::45:1;199:26:199:27:0;:16::42:1;:56::57:0;:46::72:1;:8::74;202:24:202:45:0;:::49:1;203:12:203:28:0;:31::40;:12:::1;:42:205:9:0;204:30:204:39;:20::54:1;:58::77:0;;:12::79:1;203:42:205:9;208:27:208:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;209:27:209:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;210:27:210:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;211:27:211:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;212:27:212:28:0;:16::35:1;:49::50:0;:39::57:1;:60::65:0;:39:::1;:16;:8::67;215:16:215:33:0;:37::38;:8::40:1;193:4:216:5;;;;228::237::0;;229:28:229:34;:8::36:1;;232:16:232:33:0;:37::38;:8::40:1;235:27:235:28:0;:16::43:1;:47::49:0;:8::51:1;3:0:238:1;;",
324
+ bytecode: "76009c6300c751c78800ce01207f528851ce8800cf01137f755f7f77c57c819f69c3539dc454a1690000537951876300cf557f7551cf517e537a757c6b7c6c76817b757767537952876300cf5a7f75557f77760600000000000087916976817b757c51cf527e537a757c6b7c6c75675379538800cf5f7f755a7f77760600000000000087916976817b757c51cf537e537a757c6b7c6c75686851d27b8851cd52c78851d151ce8851d351d09d51cc51c69d52ce008752ce00ce87767b9b697663c4549d686302e803776800cf01277f7501137f770376a9147c7e0288ac7e52cd8852d1008852cc9d00cc00c69d00cd00c78800d100ce8800d300d09d00d200cf8852c652cc940210279400a47602e803a06353cd52c78853d152ce8853d252cf8853cc78a269686d75516776519c63c0009d51ce00ce88c3529dc4529d788277559d52798277559d53798277559d54798277549d00cf01277f7501137f7700d2537a547a7e547a7e547a7e7b7e8800cd00c78800d100ce8800d300d09d00cc00c69d51d251cf8851cd51c78851d151ce8851d351d09d51cc51c602102794a2776776529c6351ce01207f528800ce51ce88c000a069c08bc378a06376ce5279886800d200cf8800cd00c78800d100ce8800d300d09d00cc00c602102794a269c4519c77777767539d03cc9b01b275c4519d00d10087686868",
325
+ sourceMap: "50:4:126:4;;;;52:26:52:27;:16::44:1;:58::59:0;:48::76:1;:8::78;53:73:53:74:0;:63::89:1;:96::98:0;:63::99:1;54:39:54:43:0;:8::45:1;57:26:57:27:0;:16::42:1;:8::67;60:34:60:35:0;:24::50:1;:60::62:0;:24::63:1;;:57::59:0;:24::63:1;;61:16:61:27:0;:34::41;:30::42:1;:16;:8::44;64:16:64:32:0;:36::37;:8::39:1;65:16:65:33:0;:37::38;:16:::1;:8::40;67:33:67:35:0;68:23:68:24;70:12:70:19;;:23::27;:12:::1;:29:74:9:0;71:42:71:43;:32::58:1;:65::66:0;:32::67:1;:::70;72:41:72:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;73:27:73:37:0;:23::38:1;:12::39;;70:29:74:9;74:15:85::0;:19:74:26;;:30::34;:19:::1;:36:79:9:0;75:42:75:43;:32::58:1;:67::69:0;:32::70:1;;:65::66:0;:32::70:1;;76:20:76:30:0;:34::48;:20:::1;;:12::50;77:27:77:37:0;:23::38:1;:12::39;;;78:41:78:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;74:36:79:9;79:15:85::0;80:20:80:27;;:31::35;:12::37:1;81:42:81:43:0;:32::58:1;:68::70:0;:32::71:1;;:65::67:0;:32::71:1;;82:20:82:30:0;:34::48;:20:::1;;:12::50;83:27:83:37:0;:23::38:1;:12::39;;;84:41:84:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;79:15:85:9;;74;88:27:88:28:0;:16::43:1;:47::63:0;:8::65:1;89:27:89:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;90:27:90:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;91:27:91:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;92:27:92:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;95:35:95:36:0;:25::51:1;:55::57:0;:25:::1;96:33:96:34:0;:23::49:1;:63::64:0;:53::79:1;:23;97:16:97:23:0;:27::36;:16:::1;:8::38;100:12:100:19:0;:21::53;:29::46;:50::51;:21::53:1;;101::101:37:0;:32::36;:21::37:1;;104:37:104:38:0;:27::53:1;:63::65:0;:27::66:1;;:60::62:0;:27::66:1;;105:29:105:63:0;:54::62;:29::63:1;;;106:27:106:28:0;:16::45:1;:8::63;107:27:107:28:0;:16::43:1;:47::49:0;:8::51:1;108:27:108:28:0;:16::35:1;:8::49;111:27:111:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;112:27:112:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;113:27:113:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;114:27:114:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;115:27:115:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;118:36:118:37:0;:26::44:1;:58::59:0;:47::66:1;:26;:69::74:0;:26:::1;:77::78:0;:21::79:1;120:12:120:18:0;:21::25;:12:::1;:27:125:9:0;121:31:121:32;:20::49:1;:63::64:0;:53::81:1;:12::83;122:31:122:32:0;:20::47:1;:61::62:0;:51::77:1;:12::79;123:31:123:32:0;:20::47:1;:61::62:0;:51::77:1;:12::79;124:31:124:32:0;:20::39:1;:43::49:0;:20:::1;:12::51;120:27:125:9;50:4:126:4;;;;147::178:5:0;;;;149:16:149:37;:41::42;:8::44:1;152:26:152:27:0;:16::42:1;:56::57:0;:46::72:1;:8::74;155:16:155:32:0;:36::37;:8::39:1;156:16:156:33:0;:37::38;:8::40:1;159:16:159:26:0;:::33:1;;:37::38:0;:8::40:1;160:16:160:26:0;;:::33:1;;:37::38:0;:8::40:1;161:16:161:26:0;;:::33:1;;:37::38:0;:8::40:1;162:16:162:23:0;;:::30:1;;:34::35:0;:8::37:1;165:37:165:38:0;:27::53:1;:63::65:0;:27::66:1;;:60::62:0;:27::66:1;;166::166:28:0;:16::43:1;:47::57:0;;:60::70;;:47:::1;:73::83:0;;:47:::1;:86::93:0;;:47:::1;:96::104:0;:47:::1;:8::106;167:27:167:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;168:27:168:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;169:27:169:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;170:27:170:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;173:27:173:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;174:27:174:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;175:27:175:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;176:27:176:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;177:27:177:28:0;:16::35:1;:49::50:0;:39::57:1;:60::65:0;:39:::1;:8::67;147:4:178:5;;193::219::0;;;;195:73:195:74;:63::89:1;:96::98:0;:63::99:1;196:39:196:43:0;:8::45:1;199:26:199:27:0;:16::42:1;:56::57:0;:46::72:1;:8::74;202:16:202:37:0;:40::41;:16:::1;:8::43;205:24:205:45:0;:::49:1;206:12:206:28:0;:31::40;:12:::1;:42:208:9:0;207:30:207:39;:20::54:1;:58::77:0;;:12::79:1;206:42:208:9;211:27:211:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;212:27:212:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;213:27:213:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;214:27:214:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;215:27:215:28:0;:16::35:1;:49::50:0;:39::57:1;:60::65:0;:39:::1;:16;:8::67;218:16:218:33:0;:37::38;:8::40:1;193:4:219:5;;;;231::240::0;;232:28:232:34;:8::36:1;;235:16:235:33:0;:37::38;:8::40:1;238:27:238:28:0;:16::43:1;:47::49:0;:8::51:1;3:0:241:1;;",
320
326
  logs: [
321
327
  ],
322
328
  requires: [
@@ -417,140 +423,144 @@ var debug = {
417
423
  line: 115
418
424
  },
419
425
  {
420
- ip: 248,
426
+ ip: 251,
421
427
  line: 121
422
428
  },
423
429
  {
424
- ip: 253,
430
+ ip: 256,
425
431
  line: 122
426
432
  },
427
433
  {
428
- ip: 258,
434
+ ip: 261,
429
435
  line: 123
430
436
  },
431
437
  {
432
- ip: 263,
438
+ ip: 266,
433
439
  line: 124
434
440
  },
435
441
  {
436
- ip: 275,
442
+ ip: 278,
437
443
  line: 149
438
444
  },
439
445
  {
440
- ip: 280,
446
+ ip: 283,
441
447
  line: 152
442
448
  },
443
449
  {
444
- ip: 283,
450
+ ip: 286,
445
451
  line: 155
446
452
  },
447
453
  {
448
- ip: 286,
454
+ ip: 289,
449
455
  line: 156
450
456
  },
451
457
  {
452
- ip: 291,
458
+ ip: 294,
453
459
  line: 159
454
460
  },
455
461
  {
456
- ip: 297,
462
+ ip: 300,
457
463
  line: 160
458
464
  },
459
465
  {
460
- ip: 303,
466
+ ip: 306,
461
467
  line: 161
462
468
  },
463
469
  {
464
- ip: 309,
470
+ ip: 312,
465
471
  line: 162
466
472
  },
467
473
  {
468
- ip: 333,
474
+ ip: 336,
469
475
  line: 166
470
476
  },
471
477
  {
472
- ip: 338,
478
+ ip: 341,
473
479
  line: 167
474
480
  },
475
481
  {
476
- ip: 343,
482
+ ip: 346,
477
483
  line: 168
478
484
  },
479
485
  {
480
- ip: 348,
486
+ ip: 351,
481
487
  line: 169
482
488
  },
483
489
  {
484
- ip: 353,
490
+ ip: 356,
485
491
  line: 170
486
492
  },
487
493
  {
488
- ip: 358,
494
+ ip: 361,
489
495
  line: 173
490
496
  },
491
497
  {
492
- ip: 363,
498
+ ip: 366,
493
499
  line: 174
494
500
  },
495
501
  {
496
- ip: 368,
502
+ ip: 371,
497
503
  line: 175
498
504
  },
499
505
  {
500
- ip: 373,
506
+ ip: 376,
501
507
  line: 176
502
508
  },
503
509
  {
504
- ip: 381,
510
+ ip: 384,
505
511
  line: 177
506
512
  },
507
513
  {
508
- ip: 392,
514
+ ip: 395,
509
515
  line: 196
510
516
  },
511
517
  {
512
- ip: 397,
518
+ ip: 400,
513
519
  line: 199
514
520
  },
515
521
  {
516
- ip: 408,
517
- line: 204
522
+ ip: 404,
523
+ line: 202
518
524
  },
519
525
  {
520
- ip: 414,
521
- line: 208
526
+ ip: 415,
527
+ line: 207
522
528
  },
523
529
  {
524
- ip: 419,
525
- line: 209
530
+ ip: 421,
531
+ line: 211
526
532
  },
527
533
  {
528
- ip: 424,
529
- line: 210
534
+ ip: 426,
535
+ line: 212
530
536
  },
531
537
  {
532
- ip: 429,
533
- line: 211
538
+ ip: 431,
539
+ line: 213
534
540
  },
535
541
  {
536
- ip: 437,
537
- line: 212
542
+ ip: 436,
543
+ line: 214
538
544
  },
539
545
  {
540
- ip: 441,
546
+ ip: 444,
541
547
  line: 215
542
548
  },
543
549
  {
544
550
  ip: 448,
545
- line: 229
551
+ line: 218
546
552
  },
547
553
  {
548
- ip: 452,
554
+ ip: 455,
549
555
  line: 232
550
556
  },
551
557
  {
552
- ip: 457,
558
+ ip: 459,
553
559
  line: 235
560
+ },
561
+ {
562
+ ip: 464,
563
+ line: 238
554
564
  }
555
565
  ]
556
566
  };
@@ -558,7 +568,7 @@ var compiler = {
558
568
  name: "cashc",
559
569
  version: "0.12.1"
560
570
  };
561
- var updatedAt = "2026-02-07T09:19:09.786Z";
571
+ var updatedAt = "2026-02-10T20:02:16.109Z";
562
572
  var contractArtifact = {
563
573
  contractName: contractName,
564
574
  constructorInputs: constructorInputs,