Contract con_dec_fix_4_vault


Contract Code


  
1 tad_contract = importlib.import_module('con_dec_fix_4_tad')
2
3 vaults = Hash(default_value=0)
4 stability_rate = Hash(default_value=1)
5 cdp = Hash(default_value=0)
6 stability_pool = Hash(default_value=0)
7
8 temporary_var = Variable()
9
10 @construct
11 def seed():
12 vaults['OWNER'] = ctx.caller
13 cdp['current_value'] = 0
14 vaults['list'] = [0]
15 vaults['current_number'] = 1
16
17 vaults['oracle'] = 'oracle' # dummy for testing purposes
18
19 vaults[0, 'collateral_type'] = 'currency'
20 vaults[0, 'minimum_collateralization'] = 1.5
21 vaults[0, 'minimum_auction_time'] = 259200
22 vaults[0, 'cap'] = 100000
23 vaults[0, 'weight'] = 10
24
25 stability_rate[0] = 1.1 # dummy for testing purposes
26
27
28 @export
29 def get_timestamp():
30 # https://developers.lamden.io/docs/smart-contracts/datetime-module/
31 td = now - datetime.datetime(1970, 1, 1, 0, 0, 0)
32 return fix_decimal(td.seconds)
33
34
35 @export
36 def create_vault(vault_type: int, amount_of_tad: float,
37 amount_of_collateral: float):
38 assert vault_type in vaults['list'], 'Not an available contract!'
39 collateral = importlib.import_module(
40 vaults[vault_type, 'collateral_type']) # TODO: Add interface enforcement
41 oracle = importlib.import_module(vaults['oracle'])
42
43 price = oracle.get_price(vault_type)
44
45 assert amount_of_tad > 0, 'Amount of tad must be positive!'
46 assert vaults[vault_type, 'total'] + amount_of_tad <= vaults[vault_type,
47 'cap'], 'The allowance is not sufficent!'
48
49 assert fix_decimal((amount_of_collateral * price) / \
50 amount_of_tad) >= vaults[vault_type,
51 'minimum_collateralization'], 'Not enough collateral!'
52
53 cdp_number = cdp['current_value']
54 cdp['current_value'] += 1
55
56 cdp[cdp_number, 'owner'] = ctx.caller
57 cdp[cdp_number, 'open'] = True
58
59 cdp[cdp_number, 'collateral_type'] = vaults[vault_type, 'collateral_type']
60 cdp[cdp_number, 'vault_type'] = vault_type
61 cdp[cdp_number, 'tad'] = amount_of_tad
62 cdp[cdp_number, 'collateral_amount'] = amount_of_collateral
63 cdp[cdp_number, 'time'] = get_timestamp()
64
65 collateral.approve(amount=amount_of_collateral, to=ctx.this)
66 collateral.transfer_from(amount=amount_of_collateral,
67 to=ctx.this, main_account=ctx.caller)
68
69 tad_contract.mint(amount=amount_of_tad)
70 tad_contract.transfer(amount=amount_of_tad, to=ctx.caller)
71
72 vaults[vault_type, 'issued'] += amount_of_tad
73 vaults[vault_type, 'total'] += amount_of_tad
74
75 return cdp_number
76
77
78 @export
79 def close_vault(cdp_number: int):
80 assert cdp[cdp_number, 'owner'] == ctx.caller, 'Not the owner!'
81 assert cdp[cdp_number, 'open'] == True, 'Vault has already been closed!'
82
83 collateral = importlib.import_module(
84 vaults[cdp[cdp_number, 'vault_type'], 'collateral_type'])
85
86 stability_ratio = fix_decimal(vaults[cdp[cdp_number, 'vault_type'], 'total'] / \
87 vaults[cdp[cdp_number, 'vault_type'], 'issued'])
88 redemption_cost = cdp[cdp_number, 'tad'] * stability_ratio
89 fee = redemption_cost * \
90 (stability_rate[cdp[cdp_number, 'vault_type']] **
91 (get_timestamp() - cdp[cdp_number, 'time'])) - redemption_cost
92
93 amount = redemption_cost + fee
94 tad_contract.transfer_from(
95 amount=amount, to=ctx.this, main_account=ctx.caller)
96 tad_contract.burn(amount=redemption_cost)
97
98 stability_pool[cdp[cdp_number, 'vault_type']] += fee
99
100 vaults[cdp[cdp_number, 'vault_type'], 'issued'] -= cdp[cdp_number, 'tad']
101 # This is only different if the ratio is different
102 vaults[cdp[cdp_number, 'vault_type'], 'total'] -= redemption_cost
103
104 cdp[cdp_number, 'open'] = False
105
106 # Return collateral
107 collateral.transfer(
108 amount=cdp[cdp_number, 'collateral_amount'], to=ctx.caller)
109
110 return amount
111
112
113 @export
114 def fast_force_close_vault(cdp_number: int):
115 assert_insufficent_collateral(cdp_number=cdp_number)
116 assert cdp[cdp_number, 'open'] is True, 'Vault has already been closed!'
117
118 collateral = importlib.import_module(
119 vaults[cdp[cdp_number, 'vault_type'], 'collateral_type'])
120 oracle = importlib.import_module(vaults['oracle'])
121
122 stability_ratio = fix_decimal(vaults[cdp[cdp_number, 'vault_type'],
123 'total'] / vaults[cdp[cdp_number, 'vault_type'], 'issued'])
124 redemption_cost_without_fee = cdp[cdp_number,
125 'tad'] * stability_ratio
126 redemption_cost = redemption_cost_without_fee * fix_decimal(1.1)
127 fee = redemption_cost_without_fee * \
128 (stability_rate[cdp[cdp_number, 'vault_type']]
129 ** (get_timestamp() - cdp[cdp_number, 'time'])) - redemption_cost_without_fee
130 redemption_cost += fee
131
132 amount_of_collateral = cdp[cdp_number, 'collateral_amount']
133 collateral_type = cdp[cdp_number, 'collateral_type']
134 price = oracle.get_price(cdp[cdp_number, 'vault_type'])
135 collateral_percent = fix_decimal((amount_of_collateral * price) / \
136 redemption_cost)
137
138 if collateral_percent >= fix_decimal(1.03):
139 tad_contract.transfer_from(
140 amount=redemption_cost, to=ctx.this, main_account=ctx.caller)
141 tad_contract.burn(amount=redemption_cost_without_fee)
142 amount = fix_decimal((redemption_cost * fix_decimal(1.03)) / price) # Double check this math is correct
143
144 collateral.transfer(amount=amount, to=ctx.caller)
145 collateral.transfer(amount=amount_of_collateral -
146 amount, to=cdp[cdp_number, 'owner'])
147
148 vaults[cdp[cdp_number, 'vault_type'],
149 'issued'] -= cdp[cdp_number, 'tad']
150 vaults[cdp[cdp_number, 'vault_type'],
151 'total'] -= redemption_cost_without_fee
152
153 else:
154 redemption_cost, redemption_cost_without_fee = redemption_cost * \
155 fix_decimal(collateral_percent / fix_decimal(1.03)), redemption_cost_without_fee * \
156 fix_decimal(collateral_percent / fix_decimal(1.03))
157
158 tad_contract.transfer_from(
159 amount=redemption_cost, to=ctx.this, main_account=ctx.caller)
160 tad_contract.burn(amount=redemption_cost_without_fee)
161
162 amount = cdp[cdp_number, 'collateral_amount']
163
164 # TODO: Add an assert later
165 collateral.transfer(amount=amount, to=ctx.caller)
166
167 vaults[cdp[cdp_number, 'vault_type'],
168 'issued'] -= cdp[cdp_number, 'tad']
169 vaults[cdp[cdp_number, 'vault_type'],
170 'total'] -= redemption_cost_without_fee
171
172 stability_pool[cdp[cdp_number, 'vault_type']
173 ] += redemption_cost - redemption_cost_without_fee
174
175 cdp[cdp_number, 'open'] = False
176
177 return amount
178
179
180 @export
181 def open_force_close_auction(cdp_number: int):
182 assert_insufficent_collateral(cdp_number=cdp_number)
183
184 assert cdp[cdp_number, 'owner'] != 0, 'Nonexistent cdp'
185 assert cdp[cdp_number, 'auction',
186 'open'] is not True, 'Auction is already taking place!' # Probably a redundant check, can be removed
187 assert cdp[cdp_number, 'open'] is True, 'Vault has already been closed!'
188
189 # This contract may only be bid on, and not closed
190 cdp[cdp_number, 'open'] = False
191 cdp[cdp_number, 'auction', 'open'] = True
192
193 cdp[cdp_number, 'auction', 'highest_bidder'] = ctx.caller
194 cdp[cdp_number, 'auction', 'top_bid'] = 0.0
195
196 cdp[cdp_number, 'auction', 'time'] = get_timestamp()
197
198 return True
199
200
201 @export
202 def bid_on_force_close(cdp_number: int, amount: float):
203 assert cdp[cdp_number, 'owner'] != 0, 'Nonexistent cdp'
204 assert cdp[cdp_number, 'auction',
205 'open'] is True, 'Auction is not open!'
206 assert amount > cdp[cdp_number, 'auction',
207 'top_bid'], 'There is already a higher bid!'
208
209 if cdp[cdp_number, 'auction', ctx.caller, 'bid'] is not None:
210 tad_contract.transfer_from(
211 amount=amount - cdp[cdp_number, 'auction', ctx.caller, 'bid'],
212 to=ctx.this, main_account=ctx.caller)
213
214 else:
215 tad_contract.transfer_from(
216 amount=amount, to=ctx.this, main_account=ctx.caller)
217
218 cdp[cdp_number, 'auction', 'highest_bidder'] = ctx.caller
219 cdp[cdp_number, 'auction', 'top_bid'] = amount
220 cdp[cdp_number, 'auction', ctx.caller, 'bid'] = amount
221
222 return True
223
224
225 @export
226 def settle_force_close(cdp_number: int):
227 assert cdp[cdp_number, 'owner'] != 0, 'Nonexistent cdp'
228 assert cdp[cdp_number, 'auction', 'open'] is True, 'Auction is not open!'
229
230 assert get_timestamp() - cdp[cdp_number, 'auction', 'time'] > vaults[cdp[cdp_number, 'vault_type'],
231 'minimum_auction_time'], 'Auction is still open!'
232
233 collateral = importlib.import_module(
234 vaults[cdp[cdp_number, 'vault_type'], 'collateral_type'])
235
236 cdp[cdp_number, 'auction', 'settled'] = True
237 cdp[cdp_number, 'open'] = False
238 cdp[cdp_number, 'auction', 'open'] = False
239
240 cdp[cdp_number, 'auction', cdp[cdp_number,
241 'auction', 'highest_bidder'], 'bid'] = 0
242
243 fee = cdp[cdp_number, 'auction', 'top_bid'] * 0.1
244 collateral.transfer_from(
245 amount=cdp[cdp_number, 'collateral_amount'], to=ctx.caller, main_account=ctx.this)
246 tad_contract.burn(amount=cdp[cdp_number, 'auction', 'top_bid'] - fee)
247
248 stability_pool[cdp[cdp_number, 'vault_type']] += fee
249
250 vaults[cdp[cdp_number, 'vault_type'], 'issued'] -= cdp[cdp_number, 'tad']
251 vaults[cdp[cdp_number, 'vault_type'],
252 'total'] -= cdp[cdp_number, 'auction', 'top_bid'] - fee # Fee is not burned, so it does not count
253
254 return cdp[cdp_number, 'auction', 'highest_bidder'], cdp[cdp_number,
255 'auction', 'top_bid']
256
257
258 @export
259 def claim_unwon_bid(cdp_number: int):
260 assert cdp[cdp_number, 'owner'] != 0, 'Nonexistent cdp'
261 assert cdp[cdp_number, 'auction',
262 'settled'] is True, 'Auction is still open or not opened!'
263
264 tad_contract.transfer(
265 to=ctx.caller, amount=cdp[cdp_number, 'auction', ctx.caller, 'bid'])
266 cdp[cdp_number, 'auction', ctx.caller, 'bid'] = 0
267
268 return True
269
270
271 @export
272 def sync_stability_pool(vault_type: int):
273 assert vault_type in vaults['list'], 'Not an available contract!'
274
275 default_amount = vaults[vault_type, 'total'] - vaults[vault_type, 'issued']
276
277 if default_amount > stability_pool[vault_type]:
278 vaults[vault_type, 'issued'] += stability_pool[vault_type]
279 stability_pool[vault_type] = 0
280 # Return new ratio
281 return fix_decimal(vaults[vault_type, 'issued'] / vaults[vault_type, 'total'])
282
283 else: # This also applies to negatives and zeros, although those situations are unlikely
284 vaults[vault_type, 'issued'] = vaults[vault_type, 'total']
285 stability_pool[vault_type] -= default_amount
286
287 return 1.0 # The ratio is perfectly equal
288
289
290 @export
291 def export_rewards(vault_type: int, amount: float):
292 # TODO: Change DSR to something else in future
293 assert vaults[vault_type, 'DSR', 'owner'] == ctx.caller, 'Not the owner!'
294 assert stability_pool[vault_type] >= amount, 'Not enough tad in stability pool to export!'
295
296 stability_pool[vault_type] -= amount
297 tad_contract.transfer(to=ctx.caller, amount=amount)
298
299 return True
300
301
302 @export
303 def mint_rewards(amount: float): # TODO: MAKE SURE MATH CHECKS OUT
304 # TODO: Change DSR to something else in future
305 assert vaults['mint', 'DSR', 'owner'] == ctx.caller, 'Not the owner!'
306 assert amount > 0, 'Cannot mint negative amount!'
307
308 tad_contract.mint(amount=amount)
309 tad_contract.transfer(to=ctx.caller, amount=amount)
310
311 total_weight = 0
312 total_funds = amount
313
314 for vault_type in vaults['list']:
315 total_weight += vaults[vault_type, 'weight']
316
317 # To make the contract more robust, and to prevent floating point errors
318 for vault_type in vaults['list']:
319 funds_transferred = fix_decimal(
320 vaults[vault_type, 'weight'] / total_weight) * total_funds
321 vaults[vault_type, 'total'] += funds_transferred
322
323 total_funds -= funds_transferred
324 total_weight -= vaults[vault_type, 'weight']
325
326 return True
327
328
329 @export
330 def sync_burn(vault_type: int, amount: float):
331 assert vault_type in vaults['list'], 'Not an available contract!'
332
333 tad_contract.transfer_from(
334 to=ctx.this, amount=amount, main_account=ctx.caller)
335 tad_contract.burn(amount=amount)
336
337 vaults[vault_type, 'total'] -= amount
338
339 return vaults[vault_type, 'total']
340
341
342 @export
343 def add_vault(collateral_type: str, collateral_amount: float, auction_time: float,
344 max_minted: float, s_rate: float, weight: float):
345 assert vaults['OWNER'] == ctx.caller, 'Not the owner!'
346
347 vault_number = vaults['current_number']
348 vaults['list'].append(vault_number)
349 vaults['current_number'] += 1
350
351 vaults[vault_number, 'collateral_type'] = collateral_type
352 vaults[vault_number, 'minimum_collateralization'] = collateral_amount
353 vaults[vault_number, 'minimum_auction_time'] = auction_time
354 vaults[vault_number, 'cap'] = max_minted
355 vaults[vault_number, 'weight'] = weight
356
357 stability_rate[vault_number] = s_rate
358
359 return vault_number
360
361
362 @export
363 def remove_vault(vault_type: int):
364 assert vaults['OWNER'] == ctx.caller, 'Not the owner!'
365 vaults['list'].remove(vault_type)
366
367
368 @export
369 def change_state(key: str, new_value: str, convert_to_decimal: bool = False):
370 assert vaults['OWNER'] == ctx.caller, 'Not the owner!'
371 assert type(key) == str, 'Invalid type for key'
372 assert type(new_value) == str, 'Invalid type for new value'
373
374 if convert_to_decimal:
375 new_value = decimal(new_value)
376 vaults[key] = new_value
377
378 return new_value
379
380
381 @export
382 def change_any_state(key: Any, new_value: Any, convert_to_tuple: bool = False):
383 assert vaults['OWNER'] == ctx.caller, 'Not the owner!'
384
385 if convert_to_tuple:
386 key = tuple(key)
387
388 vaults[key] = new_value
389
390 return new_value
391
392
393 @export
394 def change_stability_rate(key: int, new_value: float):
395 assert vaults['OWNER'] == ctx.caller, 'Not the owner!'
396
397 stability_rate[key] = new_value
398
399 return new_value
400
401
402 @export
403 def get_collateralization_percent(cdp_number: int):
404 assert cdp[cdp_number, 'owner'] != 0, 'Nonexistent cdp'
405 # TODO: Change this from a one-liner to proper function
406 oracle = importlib.import_module(vaults['oracle'])
407
408 return cdp[cdp_number, 'collateral_amount'] * oracle.get_price(cdp[cdp_number, 'vault_type']) / cdp[cdp_number, 'tad']
409 # code to check if minimum is met would be
410 # assert cdp[cdp_number, 'collateral_amount'] >= vaults[cdp[cdp_number, 'collateral_type'], 'minimum_collateralization']
411
412
413 def assert_insufficent_collateral(cdp_number: int):
414 assert cdp[cdp_number, 'owner'] != 0, 'Nonexistent cdp'
415
416 oracle = importlib.import_module(vaults['oracle'])
417
418 assert (cdp[cdp_number, 'collateral_amount'] * oracle.get_price(cdp[cdp_number, 'vault_type']) / cdp[cdp_number, 'tad']) < \
419 vaults[cdp[cdp_number, 'collateral_type'], 'minimum_collateralization'], 'Vault above minimum collateralization!'
420
421
422 def fix_decimal(old_decimal: float):
423 temporary_var.set(old_decimal)
424 new_decimal = temporary_var.get()
425
426 return new_decimal
427

Byte Code

e30000000000000000000000000800000040000000731e02000065006a01640083015a02650364016402640364048d035a04650364056402640664048d035a05650364016402640764048d035a06650364016402640864048d035a07650864026409640a8d025a09640b640c84005a0a650b64028301640d640e840083015a0c650b64028301650d650e650e640f9c0364106411840483015a0f650b64028301650d64129c0164136414840483015a10650b64028301650d64129c0164156416840483015a11650b64028301650d64129c0164176418840483015a12650b64028301650d650e64199c02641a641b840483015a13650b64028301650d64129c01641c641d840483015a14650b64028301650d64129c01641e641f840483015a15650b64028301650d64209c0164216422840483015a16650b64028301650d650e64239c0264246425840483015a17650b64028301650e64269c0164276428840483015a18650b64028301650d650e64239c026429642a840483015a19650b64028301651a650e650e650e650e650e642b9c06642c642d840483015a1b650b64028301650d64209c01642e642f840483015a1c650b640283016442651a651a651d64319c0364326433840583015a1e650b640283016443651f651f651d64349c0364356436840583015a20650b64028301650d650e64379c0264386439840483015a21650b64028301650d64129c01643a643b840483015a22650d64129c01643c643d84045a23650e643e9c01643f644084045a24644153002944da11636f6e5f6465635f6669785f345f746164e900000000da13636f6e5f6465635f6669785f345f7661756c74da067661756c74732903da0d64656661756c745f76616c7565da08636f6e7472616374da046e616d65e901000000da0e73746162696c6974795f72617465da03636470da0e73746162696c6974795f706f6f6cda0d74656d706f726172795f766172290272060000007207000000630000000000000000000000000400000043000000736800000074006a01740264013c006402740364033c0064026701740264043c006405740264063c006407740264073c006408740264133c007404640a8301740264143c00640c740264153c00640e740264163c006410740264173c00740464128301740564023c006400530029184eda054f574e45527202000000da0d63757272656e745f76616c7565da046c6973747208000000da0e63757272656e745f6e756d626572da066f7261636c65da0863757272656e6379da0f636f6c6c61746572616c5f747970657a03312e35da196d696e696d756d5f636f6c6c61746572616c697a6174696f6e6980f40300da146d696e696d756d5f61756374696f6e5f74696d6569a0860100da03636170e90a000000da067765696768747a03312e312902720200000072130000002902720200000072140000002902720200000072150000002902720200000072160000002902720200000072180000002906da03637478da0663616c6c6572da085f5f7661756c7473da055f5f636470da07646563696d616cda105f5f73746162696c6974795f72617465a900721f000000721f000000da00da045f5f5f5f0c000000731600000000010a0108010a010801080108010c0108010801080172210000006300000000000000000100000008000000430000007322000000740074016a01640164026402640364036403830618007d0074027c006a038301530029044e69b2070000720800000072020000002904da036e6f77da086461746574696d65da0d5f5f6669785f646563696d616cda077365636f6e64732901da027464721f000000721f0000007220000000da0d6765745f74696d657374616d701a00000073040000000002180172270000002903da0a7661756c745f74797065da0d616d6f756e745f6f665f746164da14616d6f756e745f6f665f636f6c6c61746572616c630300000000000000070000000500000043000000737a0100007c007400640119006b067314740164028301820174026a0374007c0064036602190083017d0374026a0374006404190083017d047c046a047c0083017d057c0164056b04734e740164068301820174007c006407660219007c01170074007c006408660219006b017372740164098301820174057c027c0514007c011b00830174007c00640a660219006b0573967401640b830182017406640c19007d067406640c05001900640d370003003c0074076a0874067c06640e66023c00640f74067c06641066023c0074007c0064036602190074067c06640366023c007c0074067c06641166023c007c0174067c06641266023c007c0274067c06641366023c007409830074067c06641466023c007c036a0a7c0274076a0b64158d0201007c036a0c7c0274076a0b74076a0864168d030100740d6a0e7c0164178d010100740d6a0f7c0174076a0864158d02010074007c0064186602050019007c01370003003c0074007c0064076602050019007c01370003003c007c06530029194e720f0000007a1a4e6f7420616e20617661696c61626c6520636f6e7472616374217213000000721100000072020000007a1f416d6f756e74206f6620746164206d75737420626520706f73697469766521da05746f74616c72160000007a1f54686520616c6c6f77616e6365206973206e6f7420737566666963656e742172140000007a164e6f7420656e6f75676820636f6c6c61746572616c21720e0000007208000000da056f776e657254da046f70656e7228000000da03746164da11636f6c6c61746572616c5f616d6f756e74da0474696d652902da06616d6f756e74da02746f290372310000007232000000da0c6d61696e5f6163636f756e7429017231000000da066973737565642910721b000000da0e417373657274696f6e4572726f72da09696d706f72746c6962da0d696d706f72745f6d6f64756c65da096765745f70726963657224000000721c0000007219000000721a0000007227000000da07617070726f7665da0474686973da0d7472616e736665725f66726f6dda0c7461645f636f6e7472616374da046d696e74da087472616e73666572290772280000007229000000722a000000da0a636f6c6c61746572616c7211000000da057072696365da0a6364705f6e756d626572721f000000721f0000007220000000da0c6372656174655f7661756c7420000000733a0000000003140108010a010e010a011001100114010e0110010601080110010e010c01040110010c010c010c010e0110010a010a010c01100114011401724200000029017241000000630100000000000000060000000600000043000000735a01000074007c0064016602190074016a026b02731a740364028301820174007c0064036602190064046b027332740364058301820174046a05740674007c0064066602190064076602190083017d017407740674007c00640666021900640866021900740674007c006406660219006409660219001b0083017d0274007c00640a660219007c0214007d037c03740874007c0064066602190019007409830074007c00640b660219001800130014007c0318007d047c037c0417007d05740a6a0b7c0574016a0c74016a02640c8d030100740a6a0d7c03640d8d010100740e74007c00640666021900050019007c04370003003c00740674007c00640666021900640966020500190074007c00640a66021900380003003c00740674007c0064066602190064086602050019007c03380003003c00640e74007c00640366023c007c016a0f74007c00640f6602190074016a0264108d0201007c05530029114e722c0000007a0e4e6f7420746865206f776e657221722d000000547a1e5661756c742068617320616c7265616479206265656e20636c6f7365642172280000007213000000722b0000007234000000722e000000723000000029037231000000723200000072330000002901723100000046722f0000002902723100000072320000002910721c0000007219000000721a000000723500000072360000007237000000721b0000007224000000721e0000007227000000723c000000723b000000723a000000da046275726eda105f5f73746162696c6974795f706f6f6c723e00000029067241000000723f000000da0f73746162696c6974795f726174696fda0f726564656d7074696f6e5f636f7374da036665657231000000721f000000721f0000007220000000da0b636c6f73655f7661756c7442000000732800000000021a0118010a0110010e011e01100110011a01080114020c01180118010c011c010c010e010a0172480000006301000000000000000c0000000700000043000000739202000074007c0064018d01010074017c0064026602190064036b087322740264048301820174036a04740574017c0064056602190064066602190083017d0174036a0474056407190083017d027406740574017c00640566021900640866021900740574017c006405660219006409660219001b0083017d0374017c00640a660219007c0314007d047c0474067407640b8301830114007d057c04740874017c0064056602190019007409830074017c00640c660219001800130014007c0418007d067c057c0637007d0574017c00640d660219007d0774017c006406660219007d087c026a0a74017c0064056602190083017d0974067c077c0914007c051b0083017d0a7c0a74067407640e830183016b05900172b8740b6a0c7c05740d6a0e740d6a0f640f8d030100740b6a107c0464108d01010074067c0574067407640e8301830114007c091b0083017d0b7c016a117c0b740d6a0f64118d0201007c016a117c077c0b180074017c0064126602190064118d020100740574017c00640566021900640966020500190074017c00640a66021900380003003c00740574017c0064056602190064086602050019007c04380003003c006eae7c0574067c0a74067407640e830183011b00830114007c0474067c0a74067407640e830183011b008301140002007d057d04740b6a0c7c05740d6a0e740d6a0f640f8d030100740b6a107c0464108d01010074017c00640d660219007d0b7c016a117c0b740d6a0f64118d020100740574017c00640566021900640966020500190074017c00640a66021900380003003c00740574017c0064056602190064086602050019007c04380003003c00741274017c00640566021900050019007c057c041800370003003c00641374017c00640266023c007c0b530029144e29017241000000722d000000547a1e5661756c742068617320616c7265616479206265656e20636c6f73656421722800000072130000007211000000722b0000007234000000722e0000007a03312e317230000000722f0000007a04312e3033290372310000007232000000723300000029017231000000290272310000007232000000722c000000462913da1f5f5f6173736572745f696e737566666963656e745f636f6c6c61746572616c721c000000723500000072360000007237000000721b0000007224000000721d000000721e00000072270000007238000000723c000000723b0000007219000000723a000000721a0000007243000000723e0000007244000000290c7241000000723f00000072110000007245000000da1b726564656d7074696f6e5f636f73745f776974686f75745f66656572460000007247000000722a00000072130000007240000000da12636f6c6c61746572616c5f70657263656e747231000000721f000000721f0000007220000000da16666173745f666f7263655f636c6f73655f7661756c745b000000736200000000020a0118010a0110010e010e011e01100106010a0108011c01060108010c010c0112010801080112010a010a010c010201160110010c010e0116010e0114010a0202011401040118010a010a010c010c01100116010e011401080110010c010c01724c00000063010000000000000001000000050000004300000073a400000074007c0064018d01010074017c0064026602190064036b037322740264048301820174017c00640564066603190064076b09733c740264088301820174017c0064066602190064076b0873547402640983018201640a74017c00640666023c00640774017c006405640666033c0074036a0474017c006405640b66033c007405640c830174017c006405640d66033c007406830074017c006405640e66033c0064075300290f4e29017241000000722c00000072020000007a0f4e6f6e6578697374656e7420636470da0761756374696f6e722d000000547a2041756374696f6e20697320616c72656164792074616b696e6720706c616365217a1e5661756c742068617320616c7265616479206265656e20636c6f7365642146da0e686967686573745f6269646465727a03302e30da07746f705f626964723000000029077249000000721c00000072350000007219000000721a000000721d000000722700000029017241000000721f000000721f0000007220000000da186f70656e5f666f7263655f636c6f73655f61756374696f6e91000000731600000000020a0118010c010e0118010c010e01100112011001725000000029027241000000723100000063020000000000000002000000070000004300000073d200000074007c0064016602190064026b037318740164038301820174007c00640464056603190064066b08733274016407830182017c0174007c0064046408660319006b04734c740164098301820174007c00640474026a03640a6604190064006b09728a74046a057c0174007c00640474026a03640a66041900180074026a0674026a03640b8d0301006e1474046a057c0174026a0674026a03640b8d03010074026a0374007c006404640c66033c007c0174007c006404640866033c007c0174007c00640474026a03640a66043c0064065300290d4e722c00000072020000007a0f4e6f6e6578697374656e7420636470724d000000722d000000547a1441756374696f6e206973206e6f74206f70656e21724f0000007a1e546865726520697320616c72656164792061206869676865722062696421da036269642903723100000072320000007233000000724e0000002907721c00000072350000007219000000721a000000723c000000723b000000723a000000290272410000007231000000721f000000721f0000007220000000da126269645f6f6e5f666f7263655f636c6f7365a0000000731a000000000218011a011401060116010a011e030a010a0110010e0112017252000000630100000000000000030000000800000043000000738c01000074007c0064016602190064026b037318740164038301820174007c00640464056603190064066b08733274016407830182017402830074007c0064046408660319001800740374007c00640966021900640a660219006b0473627401640b8301820174046a05740374007c00640966021900640c6602190083017d01640674007c006404640d66033c00640e74007c00640566023c00640e74007c006404640566033c00640274007c00640474007c006404640f66031900641066043c0074007c00640464116603190074066412830114007d027c016a0774007c0064136602190074086a0974086a0a64148d030100740b6a0c74007c0064046411660319007c02180064158d010100740d74007c00640966021900050019007c02370003003c00740374007c00640966021900641666020500190074007c00641766021900380003003c00740374007c00640966021900641866020500190074007c0064046411660319007c021800380003003c0074007c006404640f6603190074007c0064046411660319006602530029194e722c00000072020000007a0f4e6f6e6578697374656e7420636470724d000000722d000000547a1441756374696f6e206973206e6f74206f70656e217230000000722800000072150000007a1641756374696f6e206973207374696c6c206f70656e217213000000da07736574746c656446724e0000007251000000724f0000007a03302e31722f0000002903723100000072320000007233000000290172310000007234000000722e000000722b000000290e721c00000072350000007227000000721b00000072360000007237000000721d000000723b0000007219000000721a000000723a000000723c0000007243000000724400000029037241000000723f0000007247000000721f000000721f0000007220000000da12736574746c655f666f7263655f636c6f7365b3000000732c000000000218011a011401160106010a0110010e010c010e021a0116010e010e011a01180118010c011801120110017254000000630100000000000000010000000700000043000000736600000074007c0064016602190064026b037318740164038301820174007c00640464056603190064066b087332740164078301820174026a0374046a0574007c00640474046a0564086604190064098d020100640274007c00640474046a05640866043c0064065300290a4e722c00000072020000007a0f4e6f6e6578697374656e7420636470724d0000007253000000547a2441756374696f6e206973207374696c6c206f70656e206f72206e6f74206f70656e65642172510000002902723200000072310000002906721c0000007235000000723c000000723e0000007219000000721a00000029017241000000721f000000721f0000007220000000da0f636c61696d5f756e776f6e5f626964ce000000730e000000000218010c010e010e011001120172550000002901722800000063010000000000000002000000050000004300000073a40000007c007400640119006b067314740164028301820174007c0064036602190074007c0064046602190018007d017c0174027c0019006b04727474007c00640466020500190074027c001900370003003c00640574027c003c00740374007c0064046602190074007c006403660219001b008301530074007c0064036602190074007c00640466023c0074027c00050019007c01380003003c0074046406830153006400530029074e720f0000007a1a4e6f7420616e20617661696c61626c6520636f6e747261637421722b000000723400000072020000007a03312e302905721b000000723500000072440000007224000000721d00000029027228000000da0e64656661756c745f616d6f756e74721f000000721f0000007220000000da1373796e635f73746162696c6974795f706f6f6cd90000007316000000000214010e010a010c01180108010e010e02140110017257000000290272280000007231000000630200000000000000020000000400000043000000735400000074007c00640164026603190074016a026b02731c740364038301820174047c0019007c016b057330740364048301820174047c00050019007c01380003003c0074056a0674016a027c0164058d0201006406530029074eda03445352722c0000007a0e4e6f7420746865206f776e6572217a2b4e6f7420656e6f7567682074616420696e2073746162696c69747920706f6f6c20746f206578706f727421290272320000007231000000542907721b0000007219000000721a00000072350000007244000000723c000000723e000000290272280000007231000000721f000000721f0000007220000000da0e6578706f72745f72657761726473e9000000730c00000000021c0106010e011001100172590000002901723100000063010000000000000005000000050000004300000073c60000007400640d190074016a026b02731674036404830182017c0064056b047326740364068301820174046a057c0064078d01010074046a0674016a027c0064088d02010064057d017c007d02782074006409190044005d147d037c0174007c03640a6602190037007d0171545700785474006409190044005d487d03740774007c03640a660219007c011b0083017c0214007d0474007c03640b6602050019007c04370003003c007c027c0438007d027c0174007c03640a6602190038007d0171765700640c5300290e4e723d0000007258000000722c0000007a0e4e6f7420746865206f776e65722172020000007a1c43616e6e6f74206d696e74206e6567617469766520616d6f756e742129017231000000290272320000007231000000720f0000007218000000722b000000542903723d0000007258000000722c0000002908721b0000007219000000721a0000007235000000723c000000723d000000723e000000722400000029057231000000da0c746f74616c5f776569676874da0b746f74616c5f66756e64737228000000da1166756e64735f7472616e73666572726564721f000000721f0000007220000000da0c6d696e745f72657761726473f3000000731e0000000002160110010c011001040104010e0114010e010c010c01140108011401725d00000063020000000000000002000000050000004300000073540000007c007400640119006b067314740164028301820174026a0374046a057c0174046a0664038d03010074026a077c0164048d01010074007c0064056602050019007c01380003003c0074007c00640566021900530029064e720f0000007a1a4e6f7420616e20617661696c61626c6520636f6e747261637421290372320000007231000000723300000029017231000000722b0000002908721b0000007235000000723c000000723b0000007219000000723a000000721a0000007243000000290272280000007231000000721f000000721f0000007220000000da0973796e635f6275726e06010000730a0000000002140114020c011401725e00000029067213000000722f000000da0c61756374696f6e5f74696d65da0a6d61785f6d696e746564da06735f726174657218000000630600000000000000070000000400000043000000738400000074006401190074016a026b02731674036402830182017400640319007d067400640419006a047c068301010074006403050019006405370003003c007c0074007c06640666023c007c0174007c06640766023c007c0274007c06640866023c007c0374007c06640966023c007c0574007c06640a66023c007c0474057c063c007c065300290b4e720d0000007a0e4e6f7420746865206f776e6572217210000000720f0000007208000000721300000072140000007215000000721600000072180000002906721b0000007219000000721a0000007235000000da06617070656e64721e00000029077213000000722f000000725f000000726000000072610000007218000000da0c7661756c745f6e756d626572721f000000721f0000007220000000da096164645f7661756c741001000073160000000003160108010e0110010c010c010c010c010c0108017264000000630100000000000000010000000200000043000000732800000074006401190074016a026b02731674036402830182017400640319006a047c00830101006400530029044e720d0000007a0e4e6f7420746865206f776e657221720f0000002905721b0000007219000000721a0000007235000000da0672656d6f766529017228000000721f000000721f0000007220000000da0c72656d6f76655f7661756c74200100007304000000000216017266000000462903da036b6579da096e65775f76616c7565da12636f6e766572745f746f5f646563696d616c630300000000000000030000000300000043000000735600000074006401190074016a026b027316740364028301820174047c00830174056b02732a740364038301820174047c01830174056b02733e74036404830182017c02724a74067c0183017d017c0174007c003c007c01530029054e720d0000007a0e4e6f7420746865206f776e6572217a14496e76616c6964207479706520666f72206b65797a1a496e76616c6964207479706520666f72206e65772076616c75652907721b0000007219000000721a0000007235000000da0474797065da03737472721d0000002903726700000072680000007269000000721f000000721f0000007220000000da0c6368616e67655f737461746526010000730e0000000002160114011401040108010801726c000000290372670000007268000000da10636f6e766572745f746f5f7475706c65630300000000000000030000000300000043000000732e00000074006401190074016a026b02731674036402830182017c02722274047c0083017d007c0174007c003c007c01530029034e720d0000007a0e4e6f7420746865206f776e6572212905721b0000007219000000721a0000007235000000da057475706c65290372670000007268000000726d000000721f000000721f0000007220000000da106368616e67655f616e795f737461746531010000730a00000000021601040108010801726f000000290272670000007268000000630200000000000000020000000300000043000000732200000074006401190074016a026b02731674036402830182017c0174047c003c007c01530029034e720d0000007a0e4e6f7420746865206f776e6572212905721b0000007219000000721a0000007235000000721e000000290272670000007268000000721f000000721f0000007220000000da156368616e67655f73746162696c6974795f726174653a01000073060000000002160108017270000000630100000000000000020000000500000043000000735000000074007c0064016602190064026b037318740164038301820174026a0374046404190083017d0174007c006405660219007c016a0574007c006406660219008301140074007c006407660219001b00530029084e722c00000072020000007a0f4e6f6e6578697374656e74206364707211000000722f0000007228000000722e0000002906721c000000723500000072360000007237000000721b0000007238000000290272410000007211000000721f000000721f0000007220000000da1d6765745f636f6c6c61746572616c697a6174696f6e5f70657263656e74410100007306000000000218010e027271000000630100000000000000020000000500000043000000737000000074007c0064016602190064026b037318740164038301820174026a0374046404190083017d0174007c006405660219007c016a0574007c006406660219008301140074007c006407660219001b00740474007c006408660219006409660219006b00736c7401640a8301820164005300290b4e722c00000072020000007a0f4e6f6e6578697374656e74206364707211000000722f0000007228000000722e000000721300000072140000007a265661756c742061626f7665206d696e696d756d20636f6c6c61746572616c697a6174696f6e212906721c000000723500000072360000007237000000721b0000007238000000290272410000007211000000721f000000721f0000007220000000724900000049010000730a000000000118010e022a01160172490000002901da0b6f6c645f646563696d616c630100000000000000020000000200000043000000731600000074006a017c008301010074006a0283007d017c01530029014e2903da0f5f5f74656d706f726172795f766172da03736574da0367657429027272000000da0b6e65775f646563696d616c721f000000721f0000007220000000722400000052010000730600000000010a01080172240000004e290146290146292572360000007237000000723c000000da0448617368721b000000721e000000721c0000007244000000da085661726961626c6572730000007221000000da085f5f6578706f72747227000000da03696e74da05666c6f617472420000007248000000724c000000725000000072520000007254000000725500000072570000007259000000725d000000725e000000726b00000072640000007266000000da04626f6f6c726c000000da03416e79726f0000007270000000727100000072490000007224000000721f000000721f000000721f0000007220000000da083c6d6f64756c653e01000000735e0000000a010e01060108010e01060108010c04080e100606010401102006011018060110350601100e060112120601101a0601100a0601100f06011209060110120601120906010401160e060110050601160a0601160806011206060110070e09