Contract con_dex_v2_test12


Contract Code


  
1 I = importlib
2
3 v1_state = ForeignHash(
4 foreign_contract="con_rocketswap_official_v1_1", foreign_name="state"
5 )
6 v1_discount = ForeignHash(
7 foreign_contract="con_rocketswap_official_v1_1", foreign_name="discount"
8 )
9
10 token_interface = [
11 I.Func("transfer", args=("amount", "to")),
12 I.Func("approve", args=("amount", "to")),
13 I.Func("transfer_from", args=("amount", "to", "main_account")),
14 ]
15
16 base = Variable()
17 pairs = Hash()
18 prices = Hash(default_value=0)
19 lp_points = Hash(default_value=0)
20 reserves = Hash(default_value=[0, 0])
21 staked_amount = Hash(default_value=0)
22 state = Hash()
23
24 @construct
25 def init(base_contract: str):
26 base.set(base_contract)
27 state["OWNER"] = ctx.caller
28
29 @export
30 def create_market(contract: str, base_amount: float = 0, token_amount: float = 0):
31 assert contract != base.get(), "Cannot create a market for the base token!"
32 assert pairs[contract] == None, "Market already exists!"
33 assert base_amount > 0 and token_amount > 0, "Must provide base amount and token amount!"
34
35 if contract == v1_state["TOKEN_CONTRACT"]:
36 assert ctx.caller == state["OWNER"], "Only operator can create this market!"
37
38 base_token = I.import_module(base.get())
39 token = I.import_module(contract)
40 assert I.enforce_interface(base_token, token_interface), "Invalid token interface!"
41 assert I.enforce_interface(token, token_interface), "Invalid token interface!"
42
43 base_balance = ForeignHash(foreign_contract=base.get(), foreign_name="balances")
44 token_balance = ForeignHash(foreign_contract=contract, foreign_name="balances")
45
46 dex_base_balance_1 = base_balance[ctx.this] or 0
47
48 base_token.transfer_from(amount=base_amount, to=ctx.this, main_account=ctx.caller)
49 token.transfer_from(amount=token_amount, to=ctx.this, main_account=ctx.caller)
50
51 dex_base_balance_2 = base_balance[ctx.this]
52 dex_token_balance = token_balance[ctx.this]
53 # get the exact amount of tokens received by contract
54 base_amount = dex_base_balance_2 - dex_base_balance_1 # after first market creation there will always be lusd in this contract so there is a need to calculate the difference for new incoming lusd amounts
55 token_amount = dex_token_balance
56
57 prices[contract] = base_amount / token_amount
58 pairs[contract] = True
59 lp_points[contract, ctx.caller] = 100
60 lp_points[contract] = 100
61 reserves[contract] = [base_amount, token_amount]
62 # return True
63 return reserves[contract]
64
65 @export
66 def liquidity_balance_of(contract: str, account: str):
67 return lp_points[contract, account]
68
69
70 @export
71 def add_liquidity(contract: str, base_amount: float = 0):
72 assert pairs[contract] is True, "Market does not exist!"
73 assert base_amount > 0, "Must provide base amount!"
74 base_token = I.import_module(base.get())
75 token = I.import_module(contract)
76 assert I.enforce_interface(base_token, token_interface), "Invalid token interface!"
77 assert I.enforce_interface(token, token_interface), "Invalid token interface!"
78
79 token_amount = base_amount / prices[contract]
80
81 base_balance = ForeignHash(foreign_contract=base.get(), foreign_name="balances")
82 token_balance = ForeignHash(foreign_contract=contract, foreign_name="balances")
83
84 dex_base_balance_1 = base_balance[ctx.this]
85 dex_token_balance_1 = token_balance[ctx.this]
86
87 base_token.transfer_from(amount=base_amount, to=ctx.this, main_account=ctx.caller)
88 token.transfer_from(amount=token_amount, to=ctx.this, main_account=ctx.caller)
89
90 dex_base_balance_2 = base_balance[ctx.this]
91 dex_token_balance_2 = token_balance[ctx.this]
92 # get the exact amount of tokens received by contract
93 base_amount = dex_base_balance_2 - dex_base_balance_1
94 token_amount = dex_token_balance_2 - dex_token_balance_1
95
96 total_lp_points = lp_points[contract]
97 base_reserve, token_reserve = reserves[contract]
98 points_per_base = total_lp_points / base_reserve
99 lp_to_mint = points_per_base * base_amount
100 lp_points[contract, ctx.caller] += lp_to_mint
101 lp_points[contract] += lp_to_mint
102 reserves[contract] = [
103 base_reserve + base_amount,
104 token_reserve + token_amount,
105 ]
106 return lp_to_mint
107
108
109 @export
110 def remove_liquidity(contract: str, amount: float = 0):
111 assert pairs[contract] is True, "Market does not exist!"
112 assert amount > 0, "Must be a positive LP point amount!"
113 assert lp_points[contract, ctx.caller] >= amount, "Not enough LP points to remove!"
114 base_token = I.import_module(base.get())
115 token = I.import_module(contract)
116 assert I.enforce_interface(base_token, token_interface), "Invalid token interface!"
117 assert I.enforce_interface(token, token_interface), "Invalid token interface!"
118 lp_percentage = amount / lp_points[contract]
119 base_reserve, token_reserve = reserves[contract]
120 base_amount = base_reserve * lp_percentage
121 token_amount = token_reserve * lp_percentage
122 base_token.transfer(to=ctx.caller, amount=base_amount)
123 token.transfer(to=ctx.caller, amount=token_amount)
124 lp_points[contract, ctx.caller] -= amount
125 lp_points[contract] -= amount
126 assert lp_points[contract] > 1, "Not enough remaining liquidity!"
127 new_base_reserve = base_reserve - base_amount
128 new_token_reserve = token_reserve - token_amount
129 assert new_base_reserve > 0 and new_token_reserve > 0, "Not enough remaining liquidity!"
130 reserves[contract] = [new_base_reserve, new_token_reserve]
131 return base_amount, token_amount
132
133
134 @export
135 def transfer_liquidity(contract: str, to: str, amount: float):
136 assert amount > 0, "Must be a positive LP point amount!"
137 assert lp_points[contract, ctx.caller] >= amount, "Not enough LP points to transfer!"
138 lp_points[contract, ctx.caller] -= amount
139 lp_points[contract, to] += amount
140
141
142 # @export
143 # def approve_liquidity(
144 # contract: str, to: str, amount: float, ctx_to_signer: bool = False
145 # ):
146 # assert amount > 0, "Cannot send negative balances!"
147 # if ctx_to_signer is True:
148 # lp_points[contract, ctx.signer, to] += amount
149 # else:
150 # lp_points[contract, ctx.caller, to] += amount
151
152 @export
153 def approve_liquidity(contract: str, to: str, amount: float):
154 assert amount > 0, 'Cannot send negative balances!'
155 lp_points[contract, ctx.caller, to] += amount
156
157
158 @export
159 def transfer_liquidity_from(contract: str, to: str, main_account: str, amount: float):
160 assert amount > 0, "Cannot send negative balances!"
161 assert lp_points[contract, main_account, ctx.caller] >= amount, f"Not enough coins approved to send! You have {lp_points[main_account, ctx.caller]} and are trying to spend {amount}"
162 assert lp_points[contract, main_account] >= amount, "Not enough coins to send!"
163 lp_points[contract, main_account, ctx.caller] -= amount
164 lp_points[contract, main_account] -= amount
165 lp_points[contract, to] += amount
166
167
168 @export
169 def buy(
170 contract: str,
171 base_amount: float,
172 minimum_received: float = 0,
173 token_fees: bool = False,
174 ):
175 assert pairs[contract] is True, "Market does not exist!"
176 assert base_amount > 0, "Must provide base amount!"
177 base_token = I.import_module(base.get())
178 token = I.import_module(contract)
179 amm_token = I.import_module(v1_state["TOKEN_CONTRACT"])
180 assert I.enforce_interface(base_token, token_interface), "Invalid token interface!"
181 assert I.enforce_interface(token, token_interface), "Invalid token interface!"
182
183 base_balance = ForeignHash(foreign_contract=base.get(), foreign_name="balances")
184 dex_base_balance_1 = base_balance[ctx.this]
185 base_token.transfer_from(amount=base_amount, to=ctx.this, main_account=ctx.caller)
186 dex_base_balance_2 = base_balance[ctx.this]
187 # get the exact amount of tokens received by contract
188 base_amount = dex_base_balance_2 - dex_base_balance_1
189
190 if contract == v1_state["TOKEN_CONTRACT"]:
191 tokens_purchased = internal_buy(
192 contract=v1_state["TOKEN_CONTRACT"], base_amount=base_amount
193 )
194
195 token.transfer(amount=tokens_purchased, to=ctx.caller)
196 return tokens_purchased
197
198 base_reserve, token_reserve = reserves[contract]
199 k = base_reserve * token_reserve
200 new_base_reserve = base_reserve + base_amount
201 new_token_reserve = k / new_base_reserve
202 tokens_purchased = token_reserve - new_token_reserve
203 fee_percent = v1_state["FEE_PERCENTAGE"] * v1_discount[ctx.caller]
204 fee = tokens_purchased * fee_percent
205
206 if token_fees is True:
207 fee = fee * v1_state["TOKEN_DISCOUNT"]
208 rswp_k = base_reserve * token_reserve
209 rswp_new_token_reserve = token_reserve + fee
210 rswp_new_base_reserve = rswp_k / rswp_new_token_reserve
211 rswp_base_purchased = base_reserve - rswp_new_base_reserve
212 rswp_base_purchased += rswp_base_purchased * fee_percent
213 rswp_base_reserve_2, rswp_token_reserve_2 = reserves[v1_state["TOKEN_CONTRACT"]]
214 rswp_k_2 = rswp_base_reserve_2 * rswp_token_reserve_2
215 rswp_new_base_reserve_2 = rswp_base_reserve_2 + rswp_base_purchased
216 rswp_new_base_reserve_2 += rswp_base_purchased * fee_percent
217 rswp_new_token_reserve_2 = rswp_k_2 / rswp_new_base_reserve_2
218 sell_amount = rswp_token_reserve_2 - rswp_new_token_reserve_2
219 sell_amount_with_fee = sell_amount * v1_state["BURN_PERCENTAGE"]
220 amm_token.transfer_from(
221 amount=sell_amount, to=ctx.this, main_account=ctx.caller
222 )
223 base_received = internal_sell(
224 contract=v1_state["TOKEN_CONTRACT"], token_amount=sell_amount_with_fee
225 )
226 amm_token.transfer(
227 amount=sell_amount - sell_amount_with_fee, to=v1_state["BURN_ADDRESS"]
228 )
229 token_received = internal_buy(contract=contract, base_amount=base_received)
230
231 new_base_reserve += (
232 reserves[contract][0] - base_reserve
233 )
234 new_token_reserve += (
235 reserves[contract][1] - token_reserve
236 )
237 new_token_reserve = new_token_reserve + token_received
238 else:
239 tokens_purchased = tokens_purchased - fee
240 burn_amount = internal_buy(
241 contract=v1_state["TOKEN_CONTRACT"],
242 base_amount=internal_sell(
243 contract=contract, token_amount=fee - fee * v1_state["BURN_PERCENTAGE"]
244 ),
245 )
246 new_base_reserve += reserves[contract][0] - base_reserve
247 new_token_reserve += reserves[contract][1] - token_reserve
248 new_token_reserve = new_token_reserve + fee * v1_state["BURN_PERCENTAGE"]
249 amm_token.transfer(amount=burn_amount, to=v1_state["BURN_ADDRESS"])
250
251 if minimum_received != None:
252 assert tokens_purchased >= minimum_received, f"Only {tokens_purchased} tokens can be purchased, which is less than your minimum, which is {minimum_received} tokens."
253 assert tokens_purchased > 0, "Token reserve error!"
254
255 token.transfer(amount=tokens_purchased, to=ctx.caller)
256 reserves[contract] = [new_base_reserve, new_token_reserve]
257 prices[contract] = new_base_reserve / new_token_reserve
258 return tokens_purchased
259
260
261 @export
262 def sell(
263 contract: str,
264 token_amount: float,
265 minimum_received: float = 0,
266 token_fees: bool = False,
267 ):
268 assert pairs[contract] is True, "Market does not exist!"
269 assert token_amount > 0, "Must provide base amount and token amount!"
270 base_token = I.import_module(base.get())
271 token = I.import_module(contract)
272 amm_token = I.import_module(v1_state["TOKEN_CONTRACT"])
273 assert I.enforce_interface(base_token, token_interface), "Invalid token interface!"
274 assert I.enforce_interface(token, token_interface), "Invalid token interface!"
275
276 token_balance = ForeignHash(foreign_contract=contract, foreign_name="balances")
277 dex_token_balance_1 = token_balance[ctx.this]
278 token.transfer_from(amount=token_amount, to=ctx.this, main_account=ctx.caller)
279 dex_token_balance_2 = token_balance[ctx.this]
280 # get the exact amount of tokens received by contract
281 token_amount = dex_token_balance_2 - dex_token_balance_1
282
283 if contract == v1_state["TOKEN_CONTRACT"]:
284 base_purchased = internal_sell(
285 contract=v1_state["TOKEN_CONTRACT"], token_amount=token_amount
286 )
287 base_token.transfer(amount=base_purchased, to=ctx.caller)
288 return base_purchased
289
290 base_reserve, token_reserve = reserves[contract]
291 k = base_reserve * token_reserve
292 new_token_reserve = token_reserve + token_amount
293 new_base_reserve = k / new_token_reserve
294 base_purchased = base_reserve - new_base_reserve
295 fee_percent = v1_state["FEE_PERCENTAGE"] * v1_discount[ctx.caller]
296 fee = base_purchased * fee_percent
297 if token_fees is True:
298 fee = fee * v1_state["TOKEN_DISCOUNT"]
299 rswp_base_reserve, rswp_token_reserve = reserves[v1_state["TOKEN_CONTRACT"]]
300 rswp_k = rswp_base_reserve * rswp_token_reserve
301 rswp_new_base_reserve = rswp_base_reserve + fee
302 rswp_new_base_reserve += fee * fee_percent
303 rswp_new_token_reserve = rswp_k / rswp_new_base_reserve
304 sell_amount = rswp_token_reserve - rswp_new_token_reserve
305 sell_amount_with_fee = sell_amount * v1_state["BURN_PERCENTAGE"]
306 amm_token.transfer_from(
307 amount=sell_amount, to=ctx.this, main_account=ctx.caller
308 )
309 base_received = internal_sell(
310 contract=v1_state["TOKEN_CONTRACT"], token_amount=sell_amount_with_fee
311 )
312 amm_token.transfer(
313 amount=sell_amount - sell_amount_with_fee, to=v1_state["BURN_ADDRESS"]
314 )
315 new_base_reserve = new_base_reserve + base_received
316 else:
317 base_purchased = base_purchased - fee
318 burn_amount = fee - fee * v1_state["BURN_PERCENTAGE"]
319 new_base_reserve = new_base_reserve + fee * v1_state["BURN_PERCENTAGE"]
320 token_received = internal_buy(
321 contract=v1_state["TOKEN_CONTRACT"], base_amount=burn_amount
322 )
323 amm_token.transfer(amount=token_received, to=v1_state["BURN_ADDRESS"])
324 if minimum_received != None:
325 assert base_purchased >= minimum_received, f"Only {base_purchased} TAU can be purchased, which is less than your minimum, which is {minimum_received} TAU."
326 assert base_purchased > 0, "Token reserve error!"
327
328 base_token.transfer(amount=base_purchased, to=ctx.caller)
329 reserves[contract] = [new_base_reserve, new_token_reserve]
330 prices[contract] = new_base_reserve / new_token_reserve
331 return base_purchased
332
333 @export
334 def sync_reserves(contract: str):
335 assert v1_state["SYNC_ENABLED"] is True, "Sync is not enabled!"
336
337 token_balance = ForeignHash(foreign_contract=contract, foreign_name="balances")
338 new_balance = token_balance[ctx.this]
339 assert new_balance > 0, "Cannot be a negative balance!"
340 reserves[contract][1] = new_balance
341 return new_balance
342
343 def internal_buy(contract: str, base_amount: float):
344 assert pairs[contract] is True, "RSWP Market does not exist!"
345 if base_amount <= 0:
346 return 0
347 token = I.import_module(contract)
348 assert I.enforce_interface(token, token_interface), "Invalid token interface!"
349
350 base_reserve, token_reserve = reserves[contract]
351 k = base_reserve * token_reserve
352 new_base_reserve = base_reserve + base_amount
353 new_token_reserve = k / new_base_reserve
354 tokens_purchased = token_reserve - new_token_reserve
355 fee = tokens_purchased * v1_state["FEE_PERCENTAGE"]
356 tokens_purchased -= fee
357 new_token_reserve += fee
358 assert tokens_purchased > 0, "Token reserve error!"
359 reserves[contract] = [new_base_reserve, new_token_reserve]
360 prices[contract] = new_base_reserve / new_token_reserve
361 return tokens_purchased
362
363
364 def internal_sell(contract: str, token_amount: float):
365 assert pairs[contract] is True, "RSWP Market does not exist!"
366 if token_amount <= 0:
367 return 0
368 token = I.import_module(contract)
369 assert I.enforce_interface(token, token_interface), "Invalid token interface!"
370 base_reserve, token_reserve = reserves[contract]
371 k = base_reserve * token_reserve
372 new_token_reserve = token_reserve + token_amount
373 new_base_reserve = k / new_token_reserve
374 base_purchased = base_reserve - new_base_reserve
375 fee = base_purchased * v1_state["FEE_PERCENTAGE"]
376 base_purchased -= fee
377 new_base_reserve += fee
378 assert base_purchased > 0, "Token reserve error!"
379 reserves[contract] = [new_base_reserve, new_token_reserve]
380 prices[contract] = new_base_reserve / new_token_reserve
381 return base_purchased
382

Byte Code

e3000000000000000000000000070000004000000073e801000065005a016502640064016402640364048d045a036502640064056402640664048d045a0465016a056407643e640a8d0265016a05640b643f640a8d0265016a05640c6440640a8d0267035a0665076402640e640f8d025a08650964026410640f8d025a0a650964116402641264138d035a0b650964116402641464138d035a0c65096411641167026402641564138d035a0d650964116402641664138d035a0e650964026401640f8d025a0f651064179c016418641984045a116512640283016441651065136513641a9c03641b641c840583015a1465126402830165106510641d9c02641e641f840483015a1565126402830164426510651364209c0264216422840583015a1665126402830164436510651364239c0264246425840583015a1765126402830165106510651364269c0364276428840483015a1865126402830165106510651364269c036429642a840483015a196512640283016510651065106513642b9c04642c642d840483015a1a6512640283016444651065136513651b642f9c0464306431840583015a1c6512640283016445651065136513651b64329c0464336434840583015a1d651264028301651064359c0164366437840483015a1e6510651364209c026438643984045a1f65106513643a9c02643b643c84045a20643d53002946da1c636f6e5f726f636b6574737761705f6f6666696369616c5f76315f31da057374617465da11636f6e5f6465785f76325f746573743132da0876315f73746174652904da10666f726569676e5f636f6e7472616374da0c666f726569676e5f6e616d65da08636f6e7472616374da046e616d65da08646973636f756e74da0b76315f646973636f756e74da087472616e73666572da06616d6f756e74da02746f2901da0461726773da07617070726f7665da0d7472616e736665725f66726f6dda0c6d61696e5f6163636f756e74da0462617365290272070000007208000000da057061697273e900000000da067072696365732903da0d64656661756c745f76616c756572070000007208000000da096c705f706f696e7473da087265736572766573da0d7374616b65645f616d6f756e742901da0d626173655f636f6e7472616374630100000000000000010000000300000043000000731800000074006a017c008301010074026a03740464013c006400530029024eda054f574e45522905da065f5f62617365da03736574da03637478da0663616c6c6572da075f5f73746174652901721a000000a9007221000000da00da045f5f5f5f15000000730400000000010a01722300000029037207000000da0b626173655f616d6f756e74da0c746f6b656e5f616d6f756e746303000000000000000a0000000600000043000000735a0100007c0074006a0183006b037314740264018301820174037c00190064006b02732874026402830182017c0164036b0472387c0264036b04734074026404830182017c007404640519006b02726274056a067407640619006b027362740264078301820174086a0974006a01830083017d0374086a097c0083017d0474086a0a7c03740b8302738e740264088301820174086a0a7c04740b830273a27402640883018201740c74006a0183006409640a640b640c8d047d05740c7c006409640a640d640c8d047d067c0574056a0d190070d264037d077c036a0e7c0174056a0d74056a06640e8d0301007c046a0e7c0274056a0d74056a06640e8d0301007c0574056a0d19007d087c0674056a0d19007d097c087c0718007d017c097d027c017c021b00740f7c003c00640f74037c003c00641074107c0074056a0666023c00641074107c003c007c017c02670274117c003c0074117c001900530029114e7a2a43616e6e6f74206372656174652061206d61726b657420666f7220746865206261736520746f6b656e217a164d61726b657420616c7265616479206578697374732172140000007a2a4d7573742070726f76696465206261736520616d6f756e7420616e6420746f6b656e20616d6f756e7421da0e544f4b454e5f434f4e5452414354721b0000007a254f6e6c79206f70657261746f722063616e206372656174652074686973206d61726b6574217a18496e76616c696420746f6b656e20696e7465726661636521da0862616c616e6365737203000000da0c626173655f62616c616e636529047205000000720600000072070000007208000000da0d746f6b656e5f62616c616e63652903720c000000720d000000721100000054e9640000002912721c000000da03676574da0e417373657274696f6e4572726f72da075f5f7061697273da0a5f5f76315f7374617465721e000000721f0000007220000000da0149da0d696d706f72745f6d6f64756c65da11656e666f7263655f696e74657266616365da0f746f6b656e5f696e74657266616365da0b466f726569676e48617368da04746869737210000000da085f5f707269636573da0b5f5f6c705f706f696e7473da0a5f5f7265736572766573290a720700000072240000007225000000da0a626173655f746f6b656eda05746f6b656eda0e5f5f626173655f62616c616e6365da0f5f5f746f6b656e5f62616c616e6365da126465785f626173655f62616c616e63655f31da126465785f626173655f62616c616e63655f32da116465785f746f6b656e5f62616c616e6365722100000072210000007222000000da0d6372656174655f6d61726b65741a000000734000000000020e010601140118010c01100106010e010a010e0106010e01060108010401080104010c010e010a010a0114020a010a01080104010c0108010e0108010c01723f00000029027207000000da076163636f756e74630200000000000000020000000300000043000000730c00000074007c007c0166021900530029014e29017236000000290272070000007240000000722100000072210000007222000000da146c69717569646974795f62616c616e63655f6f663f000000730200000000027241000000290272070000007224000000630200000000000000100000000600000043000000735601000074007c00190064016b08731474016402830182017c0164036b047324740164048301820174026a0374046a05830083017d0274026a037c0083017d0374026a067c02740783027350740164058301820174026a067c0374078302736474016405830182017c0174087c0019001b007d04740974046a05830064066407640864098d047d0574097c0064066407640a64098d047d067c05740a6a0b19007d077c06740a6a0b19007d087c026a0c7c01740a6a0b740a6a0d640b8d0301007c036a0c7c04740a6a0b740a6a0d640b8d0301007c05740a6a0b19007d097c06740a6a0b19007d0a7c097c0718007d017c0a7c0818007d04740e7c0019007d0b740f7c0019005c027d0c7d0d7c0b7c0c1b007d0e7c0e7c0114007d0f740e7c00740a6a0d6602050019007c0f370003003c00740e7c00050019007c0f370003003c007c0c7c0117007c0d7c0417006702740f7c003c007c0f5300290c4e547a164d61726b657420646f6573206e6f742065786973742172140000007a194d7573742070726f76696465206261736520616d6f756e74217a18496e76616c696420746f6b656e20696e74657266616365217227000000720300000072280000002904720500000072060000007207000000720800000072290000002903720c000000720d00000072110000002910722d000000722c000000722f0000007230000000721c000000722b0000007231000000723200000072350000007233000000721e00000072340000007210000000721f00000072360000007237000000291072070000007224000000723800000072390000007225000000723a000000723b000000723c000000da136465785f746f6b656e5f62616c616e63655f31723d000000da136465785f746f6b656e5f62616c616e63655f32da0f746f74616c5f6c705f706f696e7473da0c626173655f72657365727665da0d746f6b656e5f72657365727665da0f706f696e74735f7065725f62617365da0a6c705f746f5f6d696e74722100000072210000007222000000da0d6164645f6c69717569646974794400000073400000000002140110010e010a010e0106010e0106010c0108010401080104010c010a010a010a010a0114020a010a010801080108010c01080108011601100108010c01724900000029027207000000720c0000006302000000000000000b0000000400000043000000734201000074007c00190064016b08731474016402830182017c0164036b047324740164048301820174027c0074036a04660219007c016b05733e740164058301820174056a0674076a08830083017d0274056a067c0083017d0374056a097c02740a8302736a740164068301820174056a097c03740a8302737e74016406830182017c0174027c0019001b007d04740b7c0019005c027d057d067c057c0414007d077c067c0414007d087c026a0c74036a047c0764078d0201007c036a0c74036a047c0864078d02010074027c0074036a046602050019007c01380003003c0074027c00050019007c01380003003c0074027c00190064086b049001730274016409830182017c057c0718007d097c067c0818007d0a7c0964036b04900172267c0a64036b049001732e74016409830182017c097c0a6702740b7c003c007c077c0866025300290a4e547a164d61726b657420646f6573206e6f742065786973742172140000007a234d757374206265206120706f736974697665204c5020706f696e7420616d6f756e74217a1f4e6f7420656e6f756768204c5020706f696e747320746f2072656d6f7665217a18496e76616c696420746f6b656e20696e74657266616365212902720d000000720c000000e9010000007a1f4e6f7420656e6f7567682072656d61696e696e67206c697175696469747921290d722d000000722c0000007236000000721e000000721f000000722f0000007230000000721c000000722b000000723100000072320000007237000000720b000000290b7207000000720c00000072380000007239000000da0d6c705f70657263656e746167657245000000724600000072240000007225000000da106e65775f626173655f72657365727665da116e65775f746f6b656e5f72657365727665722100000072210000007222000000da1072656d6f76655f6c69717569646974796900000073300000000002140110010c010e010e010a010e0106010e0106010c010c010801080110011001160110011601080108011c010c01724e00000029037207000000720d000000720c00000063030000000000000003000000040000004300000073580000007c0264016b047310740064028301820174017c0074026a03660219007c026b05732a740064038301820174017c0074026a036602050019007c02380003003c0074017c007c016602050019007c02370003003c006400530029044e72140000007a234d757374206265206120706f736974697665204c5020706f696e7420616d6f756e74217a214e6f7420656e6f756768204c5020706f696e747320746f207472616e73666572212904722c0000007236000000721e000000721f00000029037207000000720d000000720c000000722100000072210000007222000000da127472616e736665725f6c697175696469747985000000730a000000000210010c010e011601724f000000630300000000000000030000000400000043000000732c0000007c0264016b047310740064028301820174017c0074026a037c016603050019007c02370003003c006400530029034e72140000007a1e43616e6e6f742073656e64206e656761746976652062616c616e636573212904722c0000007236000000721e000000721f00000029037207000000720d000000720c000000722100000072210000007222000000da11617070726f76655f6c69717569646974798e000000730400000000021001725000000029047207000000720d0000007211000000720c000000630400000000000000040000000500000043000000739e0000007c0364016b047310740064028301820174017c007c0274026a03660319007c036b0573427400640374017c0274026a03660219009b0064047c039b009d048301820174017c007c02660219007c036b05735a740064058301820174017c007c0274026a036603050019007c03380003003c0074017c007c026602050019007c03380003003c0074017c007c016602050019007c03370003003c006400530029064e72140000007a1e43616e6e6f742073656e64206e656761746976652062616c616e636573217a2c4e6f7420656e6f75676820636f696e7320617070726f76656420746f2073656e642120596f752068617665207a1920616e642061726520747279696e6720746f207370656e64207a194e6f7420656e6f75676820636f696e7320746f2073656e64212904722c0000007236000000721e000000721f00000029047207000000720d0000007211000000720c000000722100000072210000007222000000da177472616e736665725f6c69717569646974795f66726f6d940000007310000000000310010e0124010a010e0118011401725100000046290472070000007224000000da106d696e696d756d5f7265636569766564da0a746f6b656e5f66656573630400000000000000200000000800000043000000730c03000074007c00190064016b08731474016402830182017c0164036b047324740164048301820174026a0374046a05830083017d0474026a037c0083017d0574026a0374066405190083017d0674026a077c0474088302735e740164068301820174026a077c057408830273727401640683018201740974046a058300640764086409640a8d047d077c07740a6a0b19007d087c046a0c7c01740a6a0b740a6a0d640b8d0301007c07740a6a0b19007d097c097c0818007d017c007406640519006b0272e6740e7406640519007c01640c8d027d0a7c056a0f7c0a740a6a0d640d8d0201007c0a530074107c0019005c027d0b7d0c7c0b7c0c14007d0d7c0b7c0117007d0e7c0d7c0e1b007d0f7c0c7c0f18007d0a7406640e19007411740a6a0d190014007d107c0a7c1014007d117c0364016b089002722e7c117406640f190014007d117c0b7c0c14007d127c0c7c1117007d137c127c131b007d147c0b7c1418007d157c157c157c10140037007d15741074066405190019005c027d167d177c167c1714007d187c167c1517007d197c197c157c10140037007d197c187c191b007d1a7c177c1a18007d1b7c1b74066410190014007d1c7c066a0c7c1b740a6a0b740a6a0d640b8d03010074127406640519007c1c64118d027d1d7c066a0f7c1b7c1c1800740664121900640d8d020100740e7c007c1d640c8d027d1e7c0e74107c001900640319007c0b180037007d0e7c0f74107c001900641319007c0c180037007d0f7c0f7c1e17007d0f6e767c0a7c1118007d0a740e74066405190074127c007c117c117406641019001400180064118d02640c8d027d1f7c0e74107c001900640319007c0b180037007d0e7c0f74107c001900641319007c0c180037007d0f7c0f7c11740664101900140017007d0f7c066a0f7c1f740664121900640d8d0201007c0264006b03900272ce7c0a7c026b05900273ce740164147c0a9b0064157c029b0064169d05830182017c0a64036b04900273e074016417830182017c056a0f7c0a740a6a0d640d8d0201007c0e7c0f670274107c003c007c0e7c0f1b0074137c003c007c0a530029184e547a164d61726b657420646f6573206e6f742065786973742172140000007a194d7573742070726f76696465206261736520616d6f756e742172260000007a18496e76616c696420746f6b656e20696e7465726661636521722700000072030000007228000000290472050000007206000000720700000072080000002903720c000000720d00000072110000002902720700000072240000002902720c000000720d000000da0e4645455f50455243454e54414745da0e544f4b454e5f444953434f554e54da0f4255524e5f50455243454e54414745290272070000007225000000da0c4255524e5f41444452455353724a0000007a054f6e6c79207a4420746f6b656e732063616e206265207075726368617365642c207768696368206973206c657373207468616e20796f7572206d696e696d756d2c207768696368206973207a0820746f6b656e732e7a14546f6b656e2072657365727665206572726f72212914722d000000722c000000722f0000007230000000721c000000722b000000722e000000723100000072320000007233000000721e00000072340000007210000000721f000000da0e5f5f696e7465726e616c5f627579720b0000007237000000da0d5f5f76315f646973636f756e74da0f5f5f696e7465726e616c5f73656c6c72350000002920720700000072240000007252000000725300000072380000007239000000da09616d6d5f746f6b656e723a000000723c000000723d000000da10746f6b656e735f70757263686173656472450000007246000000da016b724c000000724d000000da0b6665655f70657263656e74da03666565da06727377705f6bda16727377705f6e65775f746f6b656e5f72657365727665da15727377705f6e65775f626173655f72657365727665da13727377705f626173655f707572636861736564da13727377705f626173655f726573657276655f32da14727377705f746f6b656e5f726573657276655f32da08727377705f6b5f32da17727377705f6e65775f626173655f726573657276655f32da18727377705f6e65775f746f6b656e5f726573657276655f32da0b73656c6c5f616d6f756e74da1473656c6c5f616d6f756e745f776974685f666565da0d626173655f7265636569766564da0e746f6b656e5f7265636569766564da0b6275726e5f616d6f756e74722100000072210000007222000000da03627579a1000000738e0000000003140110010e010a010e010e0106010e0106010801040108010a010a010a010a0108010c0104010c01100104010c010801080108010801120108010a010c0108010801080108010c0104010c01080108010c01080108010c010a010a0104010c010a010c0104010801140114010a0208010801060116011401140106010a0112010a012001120110010c010c01726e000000290472070000007225000000725200000072530000006304000000000000001c0000000600000043000000737c02000074007c00190064016b08731474016402830182017c0164036b047324740164048301820174026a0374046a05830083017d0474026a037c0083017d0574026a0374066405190083017d0674026a077c0474088302735e740164068301820174026a077c05740883027372740164068301820174097c00640764086409640a8d047d077c07740a6a0b19007d087c056a0c7c01740a6a0b740a6a0d640b8d0301007c07740a6a0b19007d097c097c0818007d017c007406640519006b0272e2740e7406640519007c01640c8d027d0a7c046a0f7c0a740a6a0d640d8d0201007c0a530074107c0019005c027d0b7d0c7c0b7c0c14007d0d7c0c7c0117007d0e7c0d7c0e1b007d0f7c0b7c0f18007d0a7406640e19007411740a6a0d190014007d107c0a7c1014007d117c0364016b08900172ca7c117406640f190014007d11741074066405190019005c027d127d137c127c1314007d147c127c1117007d157c157c117c10140037007d157c147c151b007d167c137c1618007d177c1774066410190014007d187c066a0c7c17740a6a0b740a6a0d640b8d030100740e7406640519007c18640c8d027d197c066a0f7c177c181800740664111900640d8d0201007c0f7c1917007d0f6e4a7c0a7c1118007d0a7c117c11740664101900140018007d1a7c0f7c11740664101900140017007d0f74127406640519007c1a64128d027d1b7c066a0f7c1b740664111900640d8d0201007c0264006b039002723e7c0a7c026b059002733e740164137c0a9b0064147c029b0064159d05830182017c0a64036b049002735074016416830182017c046a0f7c0a740a6a0d640d8d0201007c0f7c0e670274107c003c007c0f7c0e1b0074137c003c007c0a530029174e547a164d61726b657420646f6573206e6f742065786973742172140000007a2a4d7573742070726f76696465206261736520616d6f756e7420616e6420746f6b656e20616d6f756e742172260000007a18496e76616c696420746f6b656e20696e7465726661636521722700000072030000007229000000290472050000007206000000720700000072080000002903720c000000720d00000072110000002902720700000072250000002902720c000000720d00000072540000007255000000725600000072570000002902720700000072240000007a054f6e6c79207a41205441552063616e206265207075726368617365642c207768696368206973206c657373207468616e20796f7572206d696e696d756d2c207768696368206973207a05205441552e7a14546f6b656e2072657365727665206572726f72212914722d000000722c000000722f0000007230000000721c000000722b000000722e000000723100000072320000007233000000721e00000072340000007210000000721f000000725a000000720b0000007237000000725900000072580000007235000000291c720700000072250000007252000000725300000072380000007239000000725b000000723b00000072420000007243000000da0e626173655f70757263686173656472450000007246000000725d000000724d000000724c000000725e000000725f000000da11727377705f626173655f72657365727665da12727377705f746f6b656e5f726573657276657260000000726200000072610000007269000000726a000000726b000000726d000000726c000000722100000072210000007222000000da0473656c6cee00000073740000000003140110010e010a010e010e0106010e01060104010c010a0114020a0108010c0104010c01100104010c010801080108010801120108010a010c0104010c01080108010c01080108010c010a010a0104010c010a010c010a020801100106010a0104010c0112020a012001120110010c010c01727200000029017207000000630100000000000000030000000600000043000000734e00000074006401190064026b087314740164038301820174027c0064046405640664078d047d017c0174036a0419007d027c0264086b04733e74016409830182017c0274057c001900640a3c007c025300290b4eda0c53594e435f454e41424c4544547a1453796e63206973206e6f7420656e61626c6564217227000000720300000072290000002904720500000072060000007207000000720800000072140000007a1d43616e6e6f742062652061206e656761746976652062616c616e636521724a0000002906722e000000722c0000007233000000721e0000007234000000723700000029037207000000723b000000da0b6e65775f62616c616e6365722100000072210000007222000000da0d73796e635f726573657276657330010000730e0000000002140104010c010a0110010c0172750000006302000000000000000a000000030000004300000073b200000074007c00190064016b08731474016402830182017c0164036b0172206403530074026a037c0083017d0274026a047c0274058302733e740164048301820174067c0019005c027d037d047c037c0414007d057c037c0117007d067c057c061b007d077c047c0718007d087c0874076405190014007d097c087c0938007d087c077c0937007d077c0864036b04739674016406830182017c067c07670274067c003c007c067c071b0074087c003c007c08530029074e547a1b52535750204d61726b657420646f6573206e6f742065786973742172140000007a18496e76616c696420746f6b656e20696e746572666163652172540000007a14546f6b656e2072657365727665206572726f72212909722d000000722c000000722f0000007230000000723100000072320000007237000000722e0000007235000000290a72070000007224000000723900000072450000007246000000725d000000724c000000724d000000725c000000725f00000072210000007221000000722200000072580000003b010000732400000000011401080104010a010e0106010c0108010801080108010c010801080110010c010c0172580000002902720700000072250000006302000000000000000a000000030000004300000073b200000074007c00190064016b08731474016402830182017c0164036b0172206403530074026a037c0083017d0274026a047c0274058302733e740164048301820174067c0019005c027d037d047c037c0414007d057c047c0117007d067c057c061b007d077c037c0718007d087c0874076405190014007d097c087c0938007d087c077c0937007d077c0864036b04739674016406830182017c077c06670274067c003c007c077c061b0074087c003c007c08530029074e547a1b52535750204d61726b657420646f6573206e6f742065786973742172140000007a18496e76616c696420746f6b656e20696e746572666163652172540000007a14546f6b656e2072657365727665206572726f72212909722d000000722c000000722f0000007230000000723100000072320000007237000000722e0000007235000000290a72070000007225000000723900000072450000007246000000725d000000724d000000724c000000726f000000725f000000722100000072210000007222000000725a00000050010000732400000000011401080104010a010e0106010c0108010801080108010c010801080110010c010c01725a0000004e2902720c000000720d0000002902720c000000720d0000002903720c000000720d00000072110000002902721400000072140000002901721400000029017214000000290272140000004629027214000000462921da09696d706f72746c6962722f0000007233000000722e0000007259000000da0446756e637232000000da085661726961626c65721c000000da0448617368722d000000723500000072360000007237000000da0f5f5f7374616b65645f616d6f756e747220000000da037374727223000000da085f5f6578706f7274da05666c6f6174723f00000072410000007249000000724e000000724f00000072500000007251000000da04626f6f6c726e000000727200000072750000007258000000725a0000007221000000722100000072210000007222000000da083c6d6f64756c653e010000007356000000040104010c0104010c0110010e010a010c010c010e01060108010a010801060108010c030e050601162406011204060114240601141b060114080601140506010601100b06010001184b0601000118400601100a1015