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