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