Contract con_nft_marketplace_v11


Contract Code


  
1 I = importlib
2 allowed_currency = Variable()
3 operator = Variable()
4 market = Hash(default_value=0)
5 auctions = Hash(default_value=0)
6 treasury = Variable()
7 royalty_receivers = Hash(default_value=False)
8 adaptable_fee = Variable()
9
10 forced_collection_interface = [I.Func('transfer', args=('name', 'amount', 'to')), I.Func(
11 'approve', args=('amount', 'name', 'to')), I.Func('transfer_from', args=(
12 'name', 'amount', 'to', 'main_account'))]
13
14 old_royalty_receivers = ForeignHash(foreign_contract='con_nft_marketplace_v4', foreign_name='royalty_receivers')
15
16 @construct
17 def seed():
18 allowed_currency.set("currency")
19 adaptable_fee.set(2)
20 operator.set("ff61544ea94eaaeb5df08ed863c4a938e9129aba6ceee5f31b6681bdede11b89")
21 treasury.set("ff61544ea94eaaeb5df08ed863c4a938e9129aba6ceee5f31b6681bdede11b89")
22
23
24 @export
25 def sell_nft(name_of_nft: str, collection_contract: str, currency_price: float, royalty_percentage: float):
26 assert name_of_nft != "", "Name cannot be empty"
27 assert collection_contract != "", "Collection contract cannot be empty"
28 assert currency_price > 0, 'Cannot sell for negative balances!'
29 collection = I.import_module(collection_contract)
30 assert I.enforce_interface(collection, forced_collection_interface
31 ), 'Invalid collection interface!'
32 collection.transfer_from(name=name_of_nft, amount=1, to=ctx.this, main_account=ctx.caller)
33
34 listing_unique_id = block_num # block_num is a global enviroment variable that is the current block number
35
36 market[ctx.caller, collection_contract, name_of_nft, listing_unique_id] = {"amount": 1, "price": currency_price}
37
38 check_old_royalties(name_of_nft=name_of_nft,collection_contract=collection_contract)
39
40 if royalty_receivers[collection_contract, name_of_nft] == False:
41 if royalty_percentage is None:
42 royalty_percentage = 0.0
43 assert royalty_percentage <= 50, "Over 50% royalty is not allowed"
44 assert royalty_percentage >= 0, "Under 0% royalty is not allowed"
45 royalty_receivers[collection_contract, name_of_nft] = {"receiver": ctx.caller, "royalty_percentage": royalty_percentage}
46
47 return f"Successfully listed 1 {name_of_nft} for {currency_price}"
48
49
50 @export
51 def refund_nft(name_of_nft: str, collection_contract: str, listing_id: str):
52 assert name_of_nft != "", "Name cannot be empty"
53 assert collection_contract != "", "Collection contract cannot be empty"
54 assert listing_id != "", "Listing ID cannot be empty"
55 market_entry = market[ctx.caller, collection_contract, name_of_nft, listing_id]
56 collection = I.import_module(collection_contract)
57 collection.transfer(name=name_of_nft, amount=market_entry["amount"], to=ctx.caller)
58 market[ctx.caller, collection_contract, name_of_nft, listing_id] = {"amount":0, "price":market_entry["price"]}
59
60 return f"Successfully refunded {name_of_nft}"
61
62
63 @export
64 def buy_nft(name: str, collection_contract: str, seller: str, listing_id:str):
65 assert name != "", "Name cannot be empty"
66 assert collection_contract != "", "Collection contract cannot be empty"
67 assert seller != "", "Seller cannot be empty"
68 assert listing_id != "", "Listing ID cannot be empty"
69 collection = I.import_module(collection_contract)
70 currency = I.import_module(allowed_currency.get())
71 assert I.enforce_interface(collection, forced_collection_interface
72 ), 'Invalid collection interface!'
73 fee = ((market[seller, collection_contract, name, listing_id]["price"])/100*adaptable_fee.get())
74 royalty = ((market[seller, collection_contract, name, listing_id]["price"])/100*royalty_receivers[collection_contract, name]["royalty_percentage"])
75 currency.transfer_from(amount=(market[seller, collection_contract, name, listing_id]["price"]) - fee - royalty, to=seller, main_account=ctx.caller)
76 currency.transfer_from(amount=fee, to=treasury.get(), main_account=ctx.caller)
77
78 if royalty > 0:
79 currency.transfer_from(amount=royalty, to=royalty_receivers[collection_contract, name]["receiver"], main_account=ctx.caller)
80
81 old_market_entry = market[seller, collection_contract, name, listing_id]
82 market[seller, collection_contract, name, listing_id] = {"amount": 0, "price": old_market_entry["price"]}
83 collection.transfer(name=name, amount=1, to=ctx.caller)
84
85 return f"Successfully bought {name}"
86
87 @export
88 def setup_auction(name_of_nft: str, collection_contract: str, start_currency_price: float, future_royalty_percentage: float, auction_start: datetime.datetime, auction_end: datetime.datetime):
89 assert name_of_nft != "", "Name cannot be empty"
90 assert collection_contract != "", "Collection contract cannot be empty"
91 assert start_currency_price > 0, 'Cannot auction for negative balances!'
92 assert future_royalty_percentage <= 50, "Over 50% royalty is not allowed"
93 assert future_royalty_percentage >= 0, "Under 0% royalty is not allowed"
94 assert auction_start > now, 'Auction cannot start in the past!'
95 assert auction_end > auction_start, 'Auction cannot end before it starts!'
96
97 collection = I.import_module(collection_contract)
98 assert I.enforce_interface(collection, forced_collection_interface
99 ), 'Invalid collection interface!'
100 collection.transfer_from(name=name_of_nft, amount=1, to=ctx.this, main_account=ctx.caller)
101
102 listing_unique_id = block_num # block_num is a global enviroment variable that is the current block number
103 auctions[ctx.caller, collection_contract, name_of_nft, listing_unique_id] = {"current_bid": start_currency_price, "current_highest_bidder": ctx.caller, "future_royalty_percentage": future_royalty_percentage, "auction_start": auction_start, "auction_end": auction_end}
104
105 return f"Successfully listed {name_of_nft} for {start_currency_price} for auction"
106
107
108 @export
109 def bid_auction(seller: str, name_of_nft: str, collection_contract: str, auction_id: str, bid: float):
110 assert name_of_nft != "", "Name cannot be empty"
111 assert collection_contract != "", "Collection contract cannot be empty"
112 assert seller != "", "Seller cannot be empty"
113 assert auction_id != "", "Auction ID cannot be empty"
114 assert bid > 0, "Bid must be higher than 0"
115
116 auction = auctions[seller, collection_contract, name_of_nft, auction_id]
117 assert now > auction["auction_start"], "Auction has not started yet"
118 assert now < auction["auction_end"], "Auction has ended"
119
120 highest_bid = auction["current_bid"]
121 highest_bidder = auction["current_highest_bidder"]
122 assert bid > highest_bid, "Bid must be higher than the current highest bid"
123 assert highest_bidder != ctx.caller, "You are already the highest bidder"
124
125 assert seller != ctx.caller, "You cannot bid on your own auction"
126
127
128 currency = I.import_module(allowed_currency.get())
129 # refund the previous highest bidder if not the creator
130 if highest_bidder != seller:
131 currency.transfer(amount=highest_bid, to=highest_bidder)
132 currency.transfer_from(amount=bid, to=ctx.this, main_account=ctx.caller)
133 auction['current_bid'] = bid
134 auction['current_highest_bidder'] = ctx.caller
135 auctions[seller, collection_contract, name_of_nft, auction_id] = auction
136
137 return f"Successfully bid {bid} on {name_of_nft}"
138
139 @export
140 def cancel_auction(seller: str, name_of_nft: str, collection_contract: str, auction_id: str):
141 assert name_of_nft != "", "Name cannot be empty"
142 assert collection_contract != "", "Collection contract cannot be empty"
143 assert seller != "", "Seller cannot be empty"
144 assert auction_id != "", "Auction ID cannot be empty"
145
146 auction = auctions[seller, collection_contract, name_of_nft, auction_id]
147 assert auction != 0, "Auction does not exist"
148 assert now < auction["auction_start"], "Auction has already started"
149 assert ctx.caller == seller, "Only the seller can cancel the auction"
150
151 if(seller != auction["current_highest_bidder"]):
152 currency = I.import_module(allowed_currency.get())
153 currency.transfer(amount=auction["current_bid"], to=auction["current_highest_bidder"])
154 collection = I.import_module(collection_contract)
155 collection.transfer(name=name_of_nft, amount=1, to=ctx.caller)
156
157 auctions[seller, collection_contract, name_of_nft, auction_id] = 0
158
159 return f"Successfully cancelled Auction for {name_of_nft}"
160
161 @export
162 def finalize_auction(seller: str, name_of_nft: str, collection_contract: str, auction_id: str):
163 assert name_of_nft != "", "Name cannot be empty"
164 assert collection_contract != "", "Collection contract cannot be empty"
165 assert seller != "", "Seller cannot be empty"
166 assert auction_id != "", "Auction ID cannot be empty"
167
168 auction = auctions[seller, collection_contract, name_of_nft, auction_id]
169 assert auction != 0, "Auction does not exist"
170 assert now > auction["auction_end"], "Auction has not ended yet"
171
172 currency = I.import_module(allowed_currency.get())
173 to_seller = auction["current_bid"] / 100 * 98
174 to_fee = auction["current_bid"] - to_seller
175 currency.transfer(amount=to_seller, to=seller)
176 currency.transfer(amount=to_fee, to=treasury.get())
177 collection = I.import_module(collection_contract)
178 collection.transfer(name=name_of_nft, amount=1, to=auction["current_highest_bidder"])
179
180 auctions[seller, collection_contract, name_of_nft, auction_id] = 0
181 check_old_royalties(name_of_nft=name_of_nft,collection_contract=collection_contract)
182 if(royalty_receivers[collection_contract, name_of_nft] == False):
183 royalty_receivers[collection_contract, name_of_nft] = {"receiver": seller, "royalty_percentage": auction["future_royalty_percentage"]}
184
185 return f"Successfully finalized Auction for {name_of_nft}"
186
187
188 @export
189 def change_allowed_currency(contract: str):
190 assert ctx.caller == operator.get(), "Only the operator can do this"
191 allowed_currency.set(contract)
192
193 @export
194 def change_treasury(address: str):
195 assert ctx.caller == operator.get(), "Only the operator can do this"
196 treasury.set(address)
197
198 @export
199 def change_operator(address: str):
200 assert ctx.caller == operator.get(), "Only the operator can do this"
201 operator.set(address)
202
203 @export
204 def change_adaptable_fee(fee: float):
205 assert ctx.caller == operator.get(), "Only the operator can do this"
206 assert fee >= 0, "Fee cannot be negative"
207 assert fee <= 100, "Fee cannot be over 100%"
208 adaptable_fee.set(fee)
209
210 def check_old_royalties(collection_contract: str, name_of_nft: str):
211 old_royalty = old_royalty_receivers[collection_contract, name_of_nft]
212 new_royalty = royalty_receivers[collection_contract, name_of_nft]
213 if (new_royalty == False) and (old_royalty != None) and (collection_contract != "con_nameservice_v3"):
214 royalty_receivers[collection_contract, name_of_nft] = old_royalty
215 if (new_royalty == False) and (collection_contract == "con_nameservice_v3"):
216 royalty_receivers[collection_contract, name_of_nft] = {"receiver": treasury.get(), "royalty_percentage": 2}
217
218

Byte Code

e3000000000000000000000000080000004000000073d601000065005a0165026400640164028d025a0365026400640364028d025a04650564046400640564068d035a06650564046400640764068d035a0765026400640864028d025a08650564096400640a64068d035a0965026400640b64028d025a0a65016a0b640c643c64108d0265016a0b6411643d64108d0265016a0b6412643e64108d0267035a0c650d6414640a6400641564168d045a0e6417641884005a0f651064008301651165116512651264199c04641a641b840483015a13651064008301651165116511641c9c03641d641e840483015a146510640083016511651165116511641f9c0464206421840483015a15651064008301651165116512651265166a1665166a1664229c0664236424840483015a176510640083016511651165116511651264259c0564266427840483015a18651064008301651165116511651164289c046429642a840483015a19651064008301651165116511651164289c04642b642c840483015a1a6510640083016511642d9c01642e642f840483015a1b651064008301651164309c0164316432840483015a1c651064008301651164309c0164336434840483015a1d651064008301651264359c0164366437840483015a1e6511651164389c026439643a84045a1f643b5300293fda17636f6e5f6e66745f6d61726b6574706c6163655f763131da10616c6c6f7765645f63757272656e63792902da08636f6e7472616374da046e616d65da086f70657261746f72e900000000da066d61726b65742903da0d64656661756c745f76616c756572030000007204000000da0861756374696f6e73da08747265617375727946da11726f79616c74795f726563656976657273da0d616461707461626c655f666565da087472616e736665727204000000da06616d6f756e74da02746f2901da0461726773da07617070726f7665da0d7472616e736665725f66726f6dda0c6d61696e5f6163636f756e74da16636f6e5f6e66745f6d61726b6574706c6163655f7634da156f6c645f726f79616c74795f7265636569766572732904da10666f726569676e5f636f6e7472616374da0c666f726569676e5f6e616d6572030000007204000000630000000000000000000000000200000043000000732c00000074006a0164018301010074026a0164028301010074036a0164038301010074046a016403830101006400530029044eda0863757272656e6379e902000000da40666636313534346561393465616165623564663038656438363363346139333865393132396162613663656565356633316236363831626465646531316238392905da125f5f616c6c6f7765645f63757272656e6379da03736574da0f5f5f616461707461626c655f666565da0a5f5f6f70657261746f72da0a5f5f7472656173757279a90072200000007220000000da00da045f5f5f5f16000000730c00000000010a010a0104010601040172220000002904da0b6e616d655f6f665f6e6674da13636f6c6c656374696f6e5f636f6e7472616374da0e63757272656e63795f7072696365da12726f79616c74795f70657263656e7461676563040000000000000006000000060000004300000073f00000007c0064016b03731074006402830182017c0164016b03732074006403830182017c0264046b047330740064058301820174016a027c0183017d0474016a037c0474048302734e74006406830182017c046a057c00640774066a0774066a0864088d04010074097d0564077c0264099c02740a74066a087c017c007c0566043c00740b7c007c01640a8d020100740c7c017c0066021900640b6b0272e07c0364006b0872ac740d640c83017d037c03640d6b0173bc7400640e830182017c0364046b0573cc7400640f8301820174066a087c0364109c02740c7c017c0066023c0064117c009b0064127c029b009d04530029134e72210000007a144e616d652063616e6e6f7420626520656d7074797a23436f6c6c656374696f6e20636f6e74726163742063616e6e6f7420626520656d70747972060000007a2243616e6e6f742073656c6c20666f72206e656761746976652062616c616e636573217a1d496e76616c696420636f6c6c656374696f6e20696e7465726661636521e90100000029047204000000720e000000720f00000072130000002902720e000000da057072696365290272230000007224000000467a03302e30e9320000007a1f4f7665722035302520726f79616c7479206973206e6f7420616c6c6f7765647a1f556e64657220302520726f79616c7479206973206e6f7420616c6c6f7765642902da08726563656976657272260000007a165375636365737366756c6c79206c69737465642031207a0520666f7220290eda0e417373657274696f6e4572726f72da0149da0d696d706f72745f6d6f64756c65da11656e666f7263655f696e74657266616365da1b666f726365645f636f6c6c656374696f6e5f696e746572666163657212000000da03637478da0474686973da0663616c6c6572da09626c6f636b5f6e756dda085f5f6d61726b6574da155f5f636865636b5f6f6c645f726f79616c74696573da135f5f726f79616c74795f726563656976657273da07646563696d616c29067223000000722400000072250000007226000000da0a636f6c6c656374696f6eda116c697374696e675f756e697175655f6964722000000072200000007221000000da0873656c6c5f6e66741f000000732600000000031001100110010a010e0106010c010a010402180104010801100108010801100110021401723a000000290372230000007224000000da0a6c697374696e675f696463030000000000000005000000060000004300000073880000007c0064016b03731074006402830182017c0164016b03732074006403830182017c0264016b0373307400640483018201740174026a037c017c007c02660419007d0374046a057c0183017d047c046a067c007c036405190074026a0364068d03010064077c036408190064099c02740174026a037c017c007c0266043c00640a7c009b009d025300290b4e72210000007a144e616d652063616e6e6f7420626520656d7074797a23436f6c6c656374696f6e20636f6e74726163742063616e6e6f7420626520656d7074797a1a4c697374696e672049442063616e6e6f7420626520656d707479720e00000029037204000000720e000000720f000000720600000072280000002902720e00000072280000007a165375636365737366756c6c7920726566756e646564202907722b000000723400000072300000007232000000722c000000722d000000720d000000290572230000007224000000723b000000da0c6d61726b65745f656e7472797238000000722000000072200000007221000000da0a726566756e645f6e667439000000731400000000021001100110010a0108010a010c010a021c01723d000000290472040000007224000000da0673656c6c6572723b00000063040000000000000009000000060000004300000073620100007c0064016b03731074006402830182017c0164016b03732074006403830182017c0264016b03733074006404830182017c0364016b037340740064058301820174016a027c0183017d0474016a0274036a04830083017d0574016a057c0474068302736c740064068301820174077c027c017c007c03660419006407190064081b0074086a04830014007d0674077c027c017c007c03660419006407190064081b0074097c017c00660219006409190014007d077c056a0a74077c027c017c007c0366041900640719007c0618007c0718007c02740b6a0c640a8d0301007c056a0a7c06740d6a048300740b6a0c640a8d0301007c07640b6b049001721c7c056a0a7c0774097c017c0066021900640c1900740b6a0c640a8d03010074077c027c017c007c03660419007d08640b7c0864071900640d9c0274077c027c017c007c0366043c007c046a0e7c00640e740b6a0c640f8d03010064107c009b009d02530029114e72210000007a144e616d652063616e6e6f7420626520656d7074797a23436f6c6c656374696f6e20636f6e74726163742063616e6e6f7420626520656d7074797a1653656c6c65722063616e6e6f7420626520656d7074797a1a4c697374696e672049442063616e6e6f7420626520656d7074797a1d496e76616c696420636f6c6c656374696f6e20696e74657266616365217228000000e96400000072260000002903720e000000720f00000072130000007206000000722a0000002902720e0000007228000000722700000029037204000000720e000000720f0000007a145375636365737366756c6c7920626f7567687420290f722b000000722c000000722d000000721b000000da03676574722e000000722f0000007234000000721d0000007236000000721200000072300000007232000000721f000000720d000000290972040000007224000000723e000000723b00000072380000007218000000da03666565da07726f79616c7479da106f6c645f6d61726b65745f656e747279722000000072200000007221000000da076275795f6e6674480000007330000000000210011001100110010a010e010e01060220022001080104011c010a010c010a010a010801160110010201180112017244000000290672230000007224000000da1473746172745f63757272656e63795f7072696365da196675747572655f726f79616c74795f70657263656e74616765da0d61756374696f6e5f7374617274da0b61756374696f6e5f656e6463060000000000000008000000060000004300000073da0000007c0064016b03731074006402830182017c0164016b03732074006403830182017c0264046b04733074006405830182017c0364066b01734074006407830182017c0364046b05735074006408830182017c0474016b04736074006409830182017c057c046b0473707400640a8301820174026a037c0183017d0674026a047c0674058302738e7400640b830182017c066a067c00640c74076a0874076a09640d8d040100740a7d077c0274076a097c037c047c05640e9c05740b74076a097c017c007c0766043c00640f7c009b0064107c029b0064119d05530029124e72210000007a144e616d652063616e6e6f7420626520656d7074797a23436f6c6c656374696f6e20636f6e74726163742063616e6e6f7420626520656d70747972060000007a2543616e6e6f742061756374696f6e20666f72206e656761746976652062616c616e6365732172290000007a1f4f7665722035302520726f79616c7479206973206e6f7420616c6c6f7765647a1f556e64657220302520726f79616c7479206973206e6f7420616c6c6f7765647a2141756374696f6e2063616e6e6f7420737461727420696e207468652070617374217a2441756374696f6e2063616e6e6f7420656e64206265666f726520697420737461727473217a1d496e76616c696420636f6c6c656374696f6e20696e7465726661636521722700000029047204000000720e000000720f00000072130000002905da0b63757272656e745f626964da1663757272656e745f686967686573745f6269646465727246000000724700000072480000007a145375636365737366756c6c79206c6973746564207a0520666f72207a0c20666f722061756374696f6e290c722b000000da036e6f77722c000000722d000000722e000000722f00000072120000007230000000723100000072320000007233000000da0a5f5f61756374696f6e73290872230000007224000000724500000072460000007247000000724800000072380000007239000000722000000072200000007221000000da0d73657475705f61756374696f6e660000007322000000000410011001100110011001100110010a010e0106010c010a010402020106011802724d0000002905723e00000072230000007224000000da0a61756374696f6e5f6964da0362696463050000000000000009000000060000004300000073360100007c0164016b03731074006402830182017c0264016b03732074006403830182017c0064016b03733074006404830182017c0364016b03734074006405830182017c0464066b047350740064078301820174017c007c027c017c03660419007d0574027c05640819006b047374740064098301820174027c05640a19006b0073887400640b830182017c05640c19007d067c05640d19007d077c047c066b0473a87400640e830182017c0774036a046b0373ba7400640f830182017c0074036a046b0373cc740064108301820174056a0674076a08830083017d087c077c006b0372f07c086a097c067c0764118d0201007c086a0a7c0474036a0b74036a0464128d0301007c047c05640c3c0074036a047c05640d3c007c0574017c007c027c017c0366043c0064137c049b0064147c019b009d04530029154e72210000007a144e616d652063616e6e6f7420626520656d7074797a23436f6c6c656374696f6e20636f6e74726163742063616e6e6f7420626520656d7074797a1653656c6c65722063616e6e6f7420626520656d7074797a1a41756374696f6e2049442063616e6e6f7420626520656d70747972060000007a19426964206d75737420626520686967686572207468616e203072470000007a1b41756374696f6e20686173206e6f7420737461727465642079657472480000007a1141756374696f6e2068617320656e6465647249000000724a0000007a2f426964206d75737420626520686967686572207468616e207468652063757272656e742068696768657374206269647a22596f752061726520616c7265616479207468652068696768657374206269646465727a22596f752063616e6e6f7420626964206f6e20796f7572206f776e2061756374696f6e2902720e000000720f0000002903720e000000720f00000072130000007a115375636365737366756c6c7920626964207a04206f6e20290c722b000000724c000000724b00000072300000007232000000722c000000722d000000721b0000007240000000720d000000721200000072310000002909723e00000072230000007224000000724e000000724f000000da0761756374696f6eda0b686967686573745f626964da0e686967686573745f6269646465727218000000722000000072200000007221000000da0b6269645f61756374696f6e80000000732a000000000310011001100110011001100114011401080108011001120112010e0108010e01140108010a01100172530000002904723e00000072230000007224000000724e00000063040000000000000007000000060000004300000073ec0000007c0164016b03731074006402830182017c0264016b03732074006403830182017c0064016b03733074006404830182017c0364016b037340740064058301820174017c007c027c017c03660419007d047c0464066b037360740064078301820174027c04640819006b007374740064098301820174036a047c006b0273867400640a830182017c007c04640b19006b0372b674056a0674076a08830083017d057c056a097c04640c19007c04640b1900640d8d02010074056a067c0283017d067c066a097c01640e74036a04640f8d030100640674017c007c027c017c0366043c0064107c019b009d02530029114e72210000007a144e616d652063616e6e6f7420626520656d7074797a23436f6c6c656374696f6e20636f6e74726163742063616e6e6f7420626520656d7074797a1653656c6c65722063616e6e6f7420626520656d7074797a1a41756374696f6e2049442063616e6e6f7420626520656d70747972060000007a1641756374696f6e20646f6573206e6f7420657869737472470000007a1b41756374696f6e2068617320616c726561647920737461727465647a264f6e6c79207468652073656c6c65722063616e2063616e63656c207468652061756374696f6e724a00000072490000002902720e000000720f000000722700000029037204000000720e000000720f0000007a235375636365737366756c6c792063616e63656c6c65642041756374696f6e20666f7220290a722b000000724c000000724b00000072300000007232000000722c000000722d000000721b0000007240000000720d0000002907723e00000072230000007224000000724e000000725000000072180000007238000000722000000072200000007221000000da0e63616e63656c5f61756374696f6e9a00000073200000000003100110011001100110011001140112010c010e010c010a010a01120110017254000000630400000000000000090000000600000043000000732a0100007c0164016b03731074006402830182017c0264016b03732074006403830182017c0064016b03733074006404830182017c0364016b037340740064058301820174017c007c027c017c03660419007d047c0464066b037360740064078301820174027c04640819006b047374740064098301820174036a0474056a06830083017d057c04640a1900640b1b00640c14007d067c04640a19007c0618007d077c056a077c067c00640d8d0201007c056a077c0774086a068300640d8d02010074036a047c0283017d087c086a077c01640e7c04640f190064108d030100640674017c007c027c017c0366043c0074097c017c0264118d020100740a7c027c016602190064126b02900172207c007c046413190064149c02740a7c027c0166023c0064157c019b009d02530029164e72210000007a144e616d652063616e6e6f7420626520656d7074797a23436f6c6c656374696f6e20636f6e74726163742063616e6e6f7420626520656d7074797a1653656c6c65722063616e6e6f7420626520656d7074797a1a41756374696f6e2049442063616e6e6f7420626520656d70747972060000007a1641756374696f6e20646f6573206e6f7420657869737472480000007a1941756374696f6e20686173206e6f7420656e646564207965747249000000723f000000e9620000002902720e000000720f0000007227000000724a00000029037204000000720e000000720f0000002902722300000072240000004672460000002902722a00000072260000007a235375636365737366756c6c792066696e616c697a65642041756374696f6e20666f7220290b722b000000724c000000724b000000722c000000722d000000721b0000007240000000720d000000721f000000723500000072360000002909723e00000072230000007224000000724e00000072500000007218000000da09746f5f73656c6c6572da06746f5f6665657238000000722000000072200000007221000000da1066696e616c697a655f61756374696f6eaf000000732a000000000310011001100110011001100114010e0110010c010e0112010a010a010a0110010401080112021601725800000029017203000000630100000000000000010000000200000043000000732400000074006a0174026a0383006b027316740464018301820174056a067c00830101006400530029024e7a1d4f6e6c7920746865206f70657261746f722063616e20646f2074686973290772300000007232000000721e0000007240000000722b000000721b000000721c00000029017203000000722000000072200000007221000000da176368616e67655f616c6c6f7765645f63757272656e6379ca00000073040000000002160172590000002901da0761646472657373630100000000000000010000000200000043000000732400000074006a0174026a0383006b027316740464018301820174056a067c00830101006400530029024e7a1d4f6e6c7920746865206f70657261746f722063616e20646f2074686973290772300000007232000000721e0000007240000000722b000000721f000000721c0000002901725a000000722000000072200000007221000000da0f6368616e67655f7472656173757279d0000000730400000000021601725b000000630100000000000000010000000200000043000000732400000074006a0174026a0383006b027316740464018301820174026a057c00830101006400530029024e7a1d4f6e6c7920746865206f70657261746f722063616e20646f2074686973290672300000007232000000721e0000007240000000722b000000721c0000002901725a000000722000000072200000007221000000da0f6368616e67655f6f70657261746f72d6000000730400000000021601725c00000029017241000000630100000000000000010000000200000043000000734400000074006a0174026a0383006b02731674046401830182017c0064026b05732674046403830182017c0064046b017336740464058301820174056a067c00830101006400530029064e7a1d4f6e6c7920746865206f70657261746f722063616e20646f207468697372060000007a164665652063616e6e6f74206265206e65676174697665723f0000007a174665652063616e6e6f74206265206f7665722031303025290772300000007232000000721e0000007240000000722b000000721d000000721c00000029017241000000722000000072200000007221000000da146368616e67655f616461707461626c655f666565dc00000073080000000002160110011001725d000000290272240000007223000000630200000000000000040000000400000043000000736600000074007c007c01660219007d0274017c007c01660219007d037c0364016b02723c7c0264006b03723c7c0064026b03723c7c0274017c007c0166023c007c0364016b0272627c0064026b02726274026a038300640364049c0274017c007c0166023c006400530029054e46da12636f6e5f6e616d65736572766963655f763372190000002902722a00000072260000002904da175f5f6f6c645f726f79616c74795f7265636569766572737236000000721f0000007240000000290472240000007223000000da0b6f6c645f726f79616c7479da0b6e65775f726f79616c74797220000000722000000072210000007235000000e4000000730e00000000010c010c01100108010c01100272350000004e29037204000000720e000000720f0000002903720e0000007204000000720f00000029047204000000720e000000720f00000072130000002920da09696d706f72746c6962722c000000da085661726961626c65721b000000721e000000da04486173687234000000724c000000721f0000007236000000721d000000da0446756e63722f000000da0b466f726569676e48617368725f0000007222000000da085f5f6578706f7274da03737472da05666c6f6174723a000000723d0000007244000000da086461746574696d65724d0000007253000000725400000072580000007259000000725b000000725c000000725d00000072350000007220000000722000000072200000007221000000da083c6d6f64756c653e0100000073600000000401040108010c0106010801060108010c0104010a0104010801060116010c01020104010a0308090601040112180601140e0601161d060104010401161706010601121806010601101306010401121906011005060110050601100506011007