Contract con_gamma_phi_dao_v1


Contract Code


  
1 # con_gamma_phi_dao_v1
2
3 # Imports
4 I = importlib
5
6
7 # State
8 settings = Hash(default_value=None)
9 stakes = Hash(default_value=0)
10 total_staked = Variable()
11
12
13 # DAO
14 proposal_id = Variable()
15 finished_proposals = Hash()
16 sig = Hash(default_value=False)
17 proposal_details = Hash()
18 status = Hash()
19
20
21 # Constants
22 TOKEN_CONTRACT_STR = 'token'
23 OWNER_STR = 'owner'
24 MINIMUM_PROPOSAL_DURATION_STR = 'min_proposal_duration'
25 REQUIRED_APPROVAL_PERCENTAGE_STR = 'required_approval_percentage'
26 MINIMUM_QUORUM_STR = 'min_quorum'
27 STAKING_LOCKUP_DAYS_STR = 'stake_lockup'
28
29
30 # Actions
31 metadata = Hash(default_value=None)
32 contracts_list = Variable()
33 state = {
34 'stakes': stakes, # should this be read only?
35 'settings': settings, # should this be read only?
36 'metadata': metadata,
37 'total_staked': total_staked,
38 'TOKEN_CONTRACT_STR': TOKEN_CONTRACT_STR,
39 'OWNER_STR': OWNER_STR,
40 'MINIMUM_PROPOSAL_DURATION_STR': MINIMUM_PROPOSAL_DURATION_STR,
41 'REQUIRED_APPROVAL_PERCENTAGE_STR': REQUIRED_APPROVAL_PERCENTAGE_STR,
42 'MINIMUM_QUORUM_STR': MINIMUM_QUORUM_STR,
43 'STAKING_LOCKUP_DAYS_STR': STAKING_LOCKUP_DAYS_STR,
44 }
45 actions = Hash()
46
47
48 # Action interface
49 action_interface = [
50 I.Func('interact', args=('payload', 'state', 'caller')),
51 ]
52
53
54 @construct
55 def init(token_contract: str = 'con_phi_lst001'):
56 settings[OWNER_STR] = ctx.caller
57 settings[TOKEN_CONTRACT_STR] = token_contract
58
59 settings[STAKING_LOCKUP_DAYS_STR] = 21
60 total_staked.set(0)
61 contracts_list.set([])
62
63 # DAO
64 proposal_id.set(0)
65 settings[MINIMUM_PROPOSAL_DURATION_STR] = 7 #Number is in days
66 settings[REQUIRED_APPROVAL_PERCENTAGE_STR] = 0.5 #Keep this at 50%, unless there are special circumstances
67 settings[MINIMUM_QUORUM_STR] = 0.1 #Set minimum amount of votes needed
68
69
70 def register_action(action: str, contract: str):
71 assert actions[action] is None, 'Action already registered!'
72 # Attempt to import the contract to make sure it is already submitted
73 p = I.import_module(contract)
74
75 # Assert ownership is election_house and interface is correct
76 assert I.owner_of(p) == ctx.this, \
77 'This contract must control the action contract!'
78
79 assert I.enforce_interface(p, action_interface), \
80 'Action contract does not follow the correct interface!'
81
82 contracts = contracts_list.get()
83 contracts.append(contract)
84 contracts_list.set(contracts)
85 actions[action] = contract
86
87
88 def override_action(action: str, contract: str):
89 original_contract = actions[action]
90 assert original_contract is not None, 'Action not already registered!'
91 # Attempt to import the contract to make sure it is already submitted
92 p = I.import_module(contract)
93
94 # Assert ownership is election_house and interface is correct
95 assert I.owner_of(p) == ctx.this, \
96 'This contract must control the action contract!'
97
98 assert I.enforce_interface(p, action_interface), \
99 'Action contract does not follow the correct interface!'
100
101 contracts = contracts_list.get()
102 if original_contract in contracts:
103 contracts.remove(original_contract)
104 contracts.append(contract)
105 contracts_list.set(contracts)
106 actions[action] = contract
107
108
109 def unregister_action(action: str):
110 contract = actions[action]
111 assert contract is not None, 'Action does not exist!'
112
113 contracts = contracts_list.get()
114 if contract in contracts:
115 contracts.remove(contract)
116 contracts_list.set(contracts)
117 actions[action] = None
118
119
120 @export
121 def force_register_action(action: str, contract: str):
122 assert ctx.caller == settings[OWNER_STR], 'Only the owner can directly call this method.'
123 register_action(action, contract)
124
125
126 @export
127 def force_override_action(action: str, contract: str):
128 assert ctx.caller == settings[OWNER_STR], 'Only the owner can directly call this method.'
129 override_action(action, contract)
130
131
132 @export
133 def force_unregister_action(action: str):
134 assert ctx.caller == settings[OWNER_STR], 'Only the owner can directly call this method.'
135 unregister_action(action)
136
137
138
139 # Do not export this one
140 def interact_internal(action: str, payload: dict, caller: str) -> Any:
141 contract = actions[action]
142 assert contract is not None, 'Invalid action!'
143
144 module = I.import_module(contract)
145
146 result = module.interact(payload, state, caller)
147 return result
148
149
150 @export # Safe to export
151 def interact(action: str, payload: dict) -> Any:
152 return interact_internal(action, payload, ctx.caller)
153
154
155 # Do not export this one
156 def bulk_interact_internal(action: str, payloads: list, caller: str):
157 for payload in payloads:
158 interact_internal(action, payload, caller)
159
160
161 @export # Safe to export
162 def bulk_interact(action: str, payloads: list):
163 bulk_interact_internal(action, payloads, ctx.caller)
164
165
166 @export
167 def force_change_setting(key: str, value: Any, to_float: bool = False):
168 assert ctx.caller == settings[OWNER_STR], 'Only the owner can directly change settings.'
169 if to_float:
170 value = decimal(value)
171 settings[key] = value
172
173
174 def transfer(token_contract: str, amount: float, to: str):
175 t_c = I.import_module(token_contract)
176 t_c.transfer(amount=amount, to=to)
177
178
179 def approve(token_contract: str, amount: float, to: str):
180 t_c = I.import_module(token_contract)
181 t_c.approve(amount=amount, to=to)
182
183
184 @export
185 def force_transfer(token_contract: str, amount: float, to: str):
186 assert ctx.caller == settings[OWNER_STR], 'Only the owner can call this method.'
187 transfer(token_contract, amount, to)
188
189
190 @export
191 def force_approve(token_contract: str, amount: float, to: str):
192 assert ctx.caller == settings[OWNER_STR], 'Only the owner can call this method.'
193 approve(token_contract, amount, to)
194
195
196 @export
197 def stake(amount: float):
198 assert amount >= 0, 'Must be non-negative.'
199 current_amount = stakes[ctx.caller] or 0
200 if current_amount > amount:
201 # unstake
202 assert (stakes[ctx.caller, 'time'] + datetime.timedelta(days=1) * (settings[STAKING_LOCKUP_DAYS_STR])) <= now, "Cannot unstake yet!"
203 amount_to_unstake = current_amount - amount
204 I.import_module(settings[TOKEN_CONTRACT_STR]).transfer(
205 to=ctx.caller,
206 amount=amount_to_unstake
207 )
208 total_staked.set(total_staked.get() - amount_to_unstake)
209 elif current_amount < amount:
210 # stake
211 amount_to_stake = amount - current_amount
212 I.import_module(settings[TOKEN_CONTRACT_STR]).transfer_from(
213 to=ctx.this,
214 amount=amount_to_stake,
215 main_account=ctx.caller
216 )
217 stakes[ctx.caller, 'time'] = now
218 total_staked.set(total_staked.get() + amount_to_stake)
219 stakes[ctx.caller] = amount
220
221
222 @export
223 def create_register_action_proposal(action: str, contract: str, voting_time_in_days: int, description: str):
224 assert voting_time_in_days >= settings[MINIMUM_PROPOSAL_DURATION_STR]
225 p_id = proposal_id.get()
226 proposal_id.set(p_id + 1)
227 proposal_details[p_id, "action"] = action
228 proposal_details[p_id, "contract"] = contract
229 proposal_details[p_id, "type"] = "register_action"
230 modify_proposal(p_id, description, voting_time_in_days)
231 return p_id
232
233
234 @export
235 def create_override_action_proposal(action: str, contract: str, voting_time_in_days: int, description: str):
236 assert voting_time_in_days >= settings[MINIMUM_PROPOSAL_DURATION_STR]
237 p_id = proposal_id.get()
238 proposal_id.set(p_id + 1)
239 proposal_details[p_id, "action"] = action
240 proposal_details[p_id, "contract"] = contract
241 proposal_details[p_id, "type"] = "override_action"
242 modify_proposal(p_id, description, voting_time_in_days)
243 return p_id
244
245
246 @export
247 def create_unregister_action_proposal(action: str, voting_time_in_days: int, description: str):
248 assert voting_time_in_days >= settings[MINIMUM_PROPOSAL_DURATION_STR]
249 p_id = proposal_id.get()
250 proposal_id.set(p_id + 1)
251 proposal_details[p_id, "action"] = action
252 proposal_details[p_id, "type"] = "unregister_action"
253 modify_proposal(p_id, description, voting_time_in_days)
254 return p_id
255
256
257 @export
258 def create_interact_proposal(action: str, payload: dict, voting_time_in_days: int, description: str, caller: str = None):
259 assert voting_time_in_days >= settings[MINIMUM_PROPOSAL_DURATION_STR]
260 p_id = proposal_id.get()
261 proposal_id.set(p_id + 1)
262 proposal_details[p_id, "action"] = action
263 proposal_details[p_id, "payload"] = payload
264 if caller is not None:
265 proposal_details[p_id, "caller"] = caller
266 proposal_details[p_id, "type"] = "interact"
267 modify_proposal(p_id, description, voting_time_in_days)
268 return p_id
269
270
271 @export
272 def create_bulk_interact_proposal(action: str, payloads: dict, voting_time_in_days: int, description: str, caller: str = None):
273 assert voting_time_in_days >= settings[MINIMUM_PROPOSAL_DURATION_STR]
274 p_id = proposal_id.get()
275 proposal_id.set(p_id + 1)
276 proposal_details[p_id, "action"] = action
277 proposal_details[p_id, "payloads"] = payloads
278 if caller is not None:
279 proposal_details[p_id, "caller"] = caller
280 proposal_details[p_id, "type"] = "bulk_interact"
281 modify_proposal(p_id, description, voting_time_in_days)
282 return p_id
283
284
285 @export
286 def create_change_setting_proposal(setting: str, value: Any, voting_time_in_days: int, description: str, to_float: bool = False):
287 assert voting_time_in_days >= settings[MINIMUM_PROPOSAL_DURATION_STR]
288 assert setting != OWNER_STR, 'Only the owner can change the owner setting.'
289 p_id = proposal_id.get()
290 proposal_id.set(p_id + 1)
291 if to_float:
292 value = decimal(value)
293 proposal_details[p_id, "setting"] = setting
294 proposal_details[p_id, "value"] = value
295 proposal_details[p_id, "type"] = "change_setting"
296 modify_proposal(p_id, description, voting_time_in_days)
297 return p_id
298
299
300 @export
301 def create_transfer_proposal(token_contract: str, amount: float, to: str, description: str, voting_time_in_days: int): #Transfer tokens held by the AMM treasury here
302 assert voting_time_in_days >= settings[MINIMUM_PROPOSAL_DURATION_STR]
303 p_id = proposal_id.get()
304 proposal_id.set(p_id + 1)
305 proposal_details[p_id, "token_contract"] = token_contract
306 proposal_details[p_id, "amount"] = amount
307 proposal_details[p_id, "receiver"] = to
308 proposal_details[p_id, "type"] = "transfer"
309 modify_proposal(p_id, description, voting_time_in_days)
310 return p_id
311
312
313 @export
314 def create_approval_proposal(token_contract: str, amount: float, to: str, description: str, voting_time_in_days: int): #Approve the transfer of tokens held by the AMM treasury here
315 assert voting_time_in_days >= settings[MINIMUM_PROPOSAL_DURATION_STR]
316 p_id = proposal_id.get()
317 proposal_id.set(p_id + 1)
318 proposal_details[p_id, "token_contract"] = token_contract
319 proposal_details[p_id, "amount"] = amount
320 proposal_details[p_id, "receiver"] = to
321 proposal_details[p_id, "type"] = "approval"
322 modify_proposal(p_id, description, voting_time_in_days)
323 return p_id
324
325
326 @export
327 def vote(p_id: int, result: bool): #Vote here
328 sig[p_id, ctx.caller] = result
329 voters = proposal_details[p_id, "voters"] or []
330 assert ctx.caller not in voters, 'You have already voted.'
331 voters.append(ctx.caller)
332 proposal_details[p_id, "voters"] = voters
333
334
335 @export
336 def determine_results(p_id: int) -> bool: #Vote resolution takes place here
337 assert (proposal_details[p_id, "time"] + datetime.timedelta(days=1) * (proposal_details[p_id, "duration"])) <= now, "Proposal not over!" #Checks if proposal has concluded
338 assert finished_proposals[p_id] is not True, "Proposal already resolved" #Checks that the proposal has not been resolved before (to prevent double spends)
339 assert p_id < proposal_id.get()
340 finished_proposals[p_id] = True #Adds the proposal to the list of resolved proposals
341 approvals = 0
342 total_votes = 0
343 for x in proposal_details[p_id, "voters"]:
344 stake = stakes[x] or 0
345 if sig[p_id, x] == True:
346 approvals += stake
347 total_votes += stake
348 quorum = total_staked.get()
349 if approvals < (quorum * settings[MINIMUM_QUORUM_STR]): #Checks that the minimum approval percentage has been reached (quorum)
350 status[p_id] = False
351 return False
352 if approvals / total_votes >= settings[REQUIRED_APPROVAL_PERCENTAGE_STR]: #Checks that the approval percentage of the votes has been reached (% of total votes)
353 if proposal_details[p_id, "type"] == "transfer":
354 transfer(
355 I.import_module(proposal_details[p_id, "token_contract"]),
356 amount=proposal_details[p_id, "amount"],
357 to=proposal_details[p_id, "receiver"],
358 )
359 elif proposal_details[p_id, "type"] == "approval":
360 approve(
361 I.import_module(proposal_details[p_id, "token_contract"]),
362 amount=proposal_details[p_id, "amount"],
363 to=proposal_details[p_id, "receiver"],
364 )
365 elif proposal_details[p_id, "type"] == "register_action":
366 register_action(
367 action=proposal_details[p_id, "action"],
368 contract=proposal_details[p_id, "contract"]
369 )
370 elif proposal_details[p_id, "type"] == "unregister_action":
371 unregister_action(
372 action=proposal_details[p_id, "action"],
373 )
374 elif proposal_details[p_id, "type"] == "override_action":
375 override_action(
376 action=proposal_details[p_id, "action"],
377 contract=proposal_details[p_id, "contract"]
378 )
379 elif proposal_details[p_id, "type"] == "interact":
380 interact_internal(
381 action=proposal_details[p_id, "action"],
382 payload=proposal_details[p_id, "payload"],
383 caller=proposal_details[p_id, "caller"] or ctx.this,
384 )
385 elif proposal_details[p_id, "type"] == "bulk_interact":
386 bulk_interact_internal(
387 action=proposal_details[p_id, "action"],
388 payloads=proposal_details[p_id, "payloads"],
389 caller=proposal_details[p_id, "caller"] or ctx.this,
390 )
391 elif proposal_details[p_id, "type"] == "change_setting":
392 # allowlist settings?
393 settings[proposal_details[p_id, "setting"]] = proposal_details[p_id, "value"]
394 status[p_id] = True
395 return True
396 else:
397 status[p_id] = False
398 return False
399
400
401 @export
402 def proposal_information(p_id: int): #Get proposal information, provided as a dictionary
403 info = {
404 "setting": proposal_details[p_id, "setting"],
405 "value": proposal_details[p_id, "value"],
406 "token_contract": proposal_details[p_id, "token_contract"],
407 "proposal_creator": proposal_details[p_id, "proposal_creator"],
408 "description": proposal_details[p_id, "description"],
409 "time": proposal_details[p_id, "time"],
410 "type": proposal_details[p_id, "type"],
411 "duration": proposal_details[p_id, "duration"],
412 "receiver": proposal_details[p_id, "receiver"]
413 }
414 return info
415
416
417 def modify_proposal(p_id: int, description: str, voting_time_in_days: int):
418 proposal_details[p_id, "proposal_creator"] = ctx.caller
419 proposal_details[p_id, "description"] = description
420 proposal_details[p_id, "time"] = now
421 proposal_details[p_id, "duration"] = voting_time_in_days
422
423

Byte Code

e30000000000000000000000000b00000040000000738203000065005a01650264006401640264038d035a03650264046401640564038d035a0465056401640664078d025a0665056401640864078d025a0765026401640964078d025a086502640a6401640b64038d035a0965026401640c64078d025a0a65026401640d64078d025a0b640e5a0c640f5a0d64105a0e64115a0f64125a1064135a11650264006401641464038d035a1265056401641564078d025a136504650365126506650c650d650e650f6510651164169c0a5a1465026401641764078d025a1565016a166418646b641c8d0267015a17646c6518641e9c01641f642084055a196518651864219c026422642384045a1a6518651864219c026424642584045a1b651864269c016427642884045a1c651d640183016518651864219c026429642a840483015a1e651d640183016518651864219c02642b642c840483015a1f651d64018301651864269c01642d642e840483015a206518652165186522642f9c046430643184045a23651d6401830165186521652264329c0364336418840483015a2465186525651864349c036435643684045a26651d640183016518652564379c0264386439840483015a27651d64018301646d651865226528643a9c03643b643c840583015a296518652a6518643d9c03643e643f84045a2b6518652a6518643d9c036440644184045a2c651d640183016518652a6518643d9c0364426443840483015a2d651d640183016518652a6518643d9c0364446445840483015a2e651d64018301652a64469c0164476448840483015a2f651d64018301651865186530651864499c04644a644b840483015a31651d64018301651865186530651864499c04644c644d840483015a32651d64018301651865306518644e9c03644f6450840483015a33651d64018301646e6518652165306518651864519c0564526453840583015a34651d64018301646f6518652165306518651864549c0564556456840583015a35651d6401830164706518652265306518652864579c0564586459840583015a36651d640183016518652a651865186530645a9c05645b645c840483015a37651d640183016518652a651865186530645a9c05645d645e840483015a38651d6401830165306528645f9c0264606461840483015a39651d640183016530652864629c0264636464840483015a3a651d64018301653064659c0164666467840483015a3b65306518653064689c036469646a84045a3c6400530029714eda14636f6e5f67616d6d615f7068695f64616f5f7631da0873657474696e67732903da0d64656661756c745f76616c7565da08636f6e7472616374da046e616d65e900000000da067374616b6573da0c746f74616c5f7374616b6564290272040000007205000000da0b70726f706f73616c5f6964da1266696e69736865645f70726f706f73616c7346da03736967da1070726f706f73616c5f64657461696c73da06737461747573da05746f6b656eda056f776e6572da156d696e5f70726f706f73616c5f6475726174696f6eda1c72657175697265645f617070726f76616c5f70657263656e74616765da0a6d696e5f71756f72756dda0c7374616b655f6c6f636b7570da086d65746164617461da0e636f6e7472616374735f6c697374290a7207000000720200000072140000007208000000da12544f4b454e5f434f4e54524143545f535452da094f574e45525f535452da1d4d494e494d554d5f50524f504f53414c5f4455524154494f4e5f535452da2052455155495245445f415050524f56414c5f50455243454e544147455f535452da124d494e494d554d5f51554f52554d5f535452da175354414b494e475f4c4f434b55505f444159535f535452da07616374696f6e73da08696e746572616374da077061796c6f6164da057374617465da0663616c6c65722901da0461726773da0e636f6e5f7068695f6c73743030312901da0e746f6b656e5f636f6e7472616374630100000000000000010000000300000043000000735c00000074006a01740274033c007c00740274043c006401740274053c0074066a0764028301010074086a0767008301010074096a0764028301010064037402740a3c00740b640483017402740c3c00740b640583017402740d3c006400530029064ee9150000007206000000e9070000007a03302e357a03302e31290eda036374787220000000da0a5f5f73657474696e677372170000007216000000721b000000da0e5f5f746f74616c5f7374616b6564da03736574da105f5f636f6e7472616374735f6c697374da0d5f5f70726f706f73616c5f69647218000000da07646563696d616c7219000000721a00000029017223000000a900722d000000da00da045f5f5f5f23000000731200000000010a01080108010a010a010a0108010c01722f0000002902da06616374696f6e7204000000630200000000000000040000000300000043000000737200000074007c00190064006b087314740164018301820174026a037c0183017d0274026a047c02830174056a066b027336740164028301820174026a077c0274088302734a740164038301820174096a0a83007d037c036a0b7c018301010074096a0c7c03830101007c0174007c003c006400530029044e7a1a416374696f6e20616c72656164792072656769737465726564217a2f5468697320636f6e7472616374206d75737420636f6e74726f6c2074686520616374696f6e20636f6e7472616374217a36416374696f6e20636f6e747261637420646f6573206e6f7420666f6c6c6f772074686520636f727265637420696e7465726661636521290dda095f5f616374696f6e73da0e417373657274696f6e4572726f72da0149da0d696d706f72745f6d6f64756c65da086f776e65725f6f667226000000da0474686973da11656e666f7263655f696e74657266616365da10616374696f6e5f696e74657266616365722a000000da03676574da06617070656e647229000000290472300000007204000000da0170da09636f6e747261637473722d000000722d000000722e000000da115f5f72656769737465725f616374696f6e2f0000007314000000000114010a01080110010e01060108010a010a01723d000000630200000000000000050000000300000043000000738800000074007c0019007d027c0264006b097318740164018301820174026a037c0183017d0374026a047c03830174056a066b02733a740164028301820174026a077c0374088302734e740164038301820174096a0a83007d047c027c046b0672687c046a0b7c02830101007c046a0c7c018301010074096a0d7c04830101007c0174007c003c006400530029044e7a1e416374696f6e206e6f7420616c72656164792072656769737465726564217a2f5468697320636f6e7472616374206d75737420636f6e74726f6c2074686520616374696f6e20636f6e7472616374217a36416374696f6e20636f6e747261637420646f6573206e6f7420666f6c6c6f772074686520636f727265637420696e7465726661636521290e723100000072320000007233000000723400000072350000007226000000723600000072370000007238000000722a0000007239000000da0672656d6f7665723a0000007229000000290572300000007204000000da116f726967696e616c5f636f6e7472616374723b000000723c000000722d000000722d000000722e000000da115f5f6f766572726964655f616374696f6e3c000000731a0000000001080110010a01080110010e010601080108010a010a010a01724000000029017230000000630100000000000000030000000300000043000000734800000074007c0019007d017c0164006b097318740164018301820174026a0383007d027c017c026b0672327c026a047c018301010074026a057c0283010100640074007c003c006400530029024e7a16416374696f6e20646f6573206e6f7420657869737421290672310000007232000000722a0000007239000000723e0000007229000000290372300000007204000000723c000000722d000000722d000000722e000000da135f5f756e72656769737465725f616374696f6e4c000000730e000000000108011001080108010a010a017241000000630200000000000000020000000300000043000000732400000074006a017402740319006b027316740464018301820174057c007c01830201006400530029024e7a2d4f6e6c7920746865206f776e65722063616e206469726563746c792063616c6c2074686973206d6574686f642e290672260000007220000000722700000072170000007232000000723d000000290272300000007204000000722d000000722d000000722e000000da15666f7263655f72656769737465725f616374696f6e5600000073060000000002100106017242000000630200000000000000020000000300000043000000732400000074006a017402740319006b027316740464018301820174057c007c01830201006400530029024e7a2d4f6e6c7920746865206f776e65722063616e206469726563746c792063616c6c2074686973206d6574686f642e2906722600000072200000007227000000721700000072320000007240000000290272300000007204000000722d000000722d000000722e000000da15666f7263655f6f766572726964655f616374696f6e5d00000073060000000002100106017243000000630100000000000000010000000300000043000000732200000074006a017402740319006b027316740464018301820174057c00830101006400530029024e7a2d4f6e6c7920746865206f776e65722063616e206469726563746c792063616c6c2074686973206d6574686f642e290672260000007220000000722700000072170000007232000000724100000029017230000000722d000000722d000000722e000000da17666f7263655f756e72656769737465725f616374696f6e640000007306000000000210010601724400000029047230000000721e0000007220000000da0672657475726e630300000000000000060000000400000043000000733400000074007c0019007d037c0364006b097318740164018301820174026a037c0383017d047c046a047c0174057c0283037d057c05530029024e7a0f496e76616c696420616374696f6e2129067231000000723200000072330000007234000000721d000000721f00000029067230000000721e00000072200000007204000000da066d6f64756c65da06726573756c74722d000000722d000000722e000000da135f5f696e7465726163745f696e7465726e616c6b000000730a0000000001080110010a010e01724800000029037230000000721e0000007245000000630200000000000000020000000400000043000000730e00000074007c007c0174016a028303530029014e290372480000007226000000722000000029027230000000721e000000722d000000722d000000722e000000721d000000730000007302000000000229037230000000da087061796c6f6164737220000000630300000000000000040000000500000043000000731e00000078187c0144005d107d0374007c007c037c0283030100710657006400530029014e290172480000002904723000000072490000007220000000721e000000722d000000722d000000722e000000da185f5f62756c6b5f696e7465726163745f696e7465726e616c78000000730400000000010a01724a000000290272300000007249000000630200000000000000020000000400000043000000731200000074007c007c0174016a02830301006400530029014e2903724a00000072260000007220000000290272300000007249000000722d000000722d000000722e000000da0d62756c6b5f696e7465726163747d00000073020000000002724b0000002903da036b6579da0576616c7565da08746f5f666c6f6174630300000000000000030000000300000043000000732e00000074006a017402740319006b02731674046401830182017c02722274057c0183017d017c0174027c003c006400530029024e7a2c4f6e6c7920746865206f776e65722063616e206469726563746c79206368616e67652073657474696e67732e290672260000007220000000722700000072170000007232000000722c0000002903724c000000724d000000724e000000722d000000722d000000722e000000da14666f7263655f6368616e67655f73657474696e6782000000730a00000000021001060104010801724f00000029037223000000da06616d6f756e74da02746f630300000000000000040000000400000043000000731c00000074006a017c0083017d037c036a027c017c0264018d0201006400530029024e290272500000007251000000290372330000007234000000da087472616e736665722904722300000072500000007251000000da03745f63722d000000722d000000722e000000da0a5f5f7472616e736665728b000000730400000000010a017254000000630300000000000000040000000400000043000000731c00000074006a017c0083017d037c036a027c017c0264018d0201006400530029024e290272500000007251000000290372330000007234000000da07617070726f766529047223000000725000000072510000007253000000722d000000722d000000722e000000da095f5f617070726f766590000000730400000000010a017256000000630300000000000000030000000400000043000000732600000074006a017402740319006b027316740464018301820174057c007c017c02830301006400530029024e7a244f6e6c7920746865206f776e65722063616e2063616c6c2074686973206d6574686f642e29067226000000722000000072270000007217000000723200000072540000002903722300000072500000007251000000722d000000722d000000722e000000da0e666f7263655f7472616e736665729500000073060000000002100106017257000000630300000000000000030000000400000043000000732600000074006a017402740319006b027316740464018301820174057c007c017c02830301006400530029024e7a244f6e6c7920746865206f776e65722063616e2063616c6c2074686973206d6574686f642e29067226000000722000000072270000007217000000723200000072560000002903722300000072500000007251000000722d000000722d000000722e000000da0d666f7263655f617070726f76659c000000730600000000021001060172580000002901725000000063010000000000000004000000050000004300000073e60000007c0064016b0573107400640283018201740174026a031900701c64017d017c017c006b04728a740174026a0364036602190074046a05640464058d017406740719001400170074086b01735474006406830182017c017c0018007d0274096a0a7406740b190083016a0c74026a037c0264078d020100740d6a0e740d6a0f83007c021800830101006e4e7c017c006b0072d87c007c0118007d0374096a0a7406740b190083016a1074026a117c0374026a0364088d0301007408740174026a03640366023c00740d6a0e740d6a0f83007c031700830101007c00740174026a033c006400530029094e72060000007a154d757374206265206e6f6e2d6e656761746976652eda0474696d65e9010000002901da04646179737a1343616e6e6f7420756e7374616b652079657421290272510000007250000000290372510000007250000000da0c6d61696e5f6163636f756e7429127232000000da085f5f7374616b657372260000007220000000da086461746574696d65da0974696d6564656c74617227000000721b000000da036e6f777233000000723400000072160000007252000000722800000072290000007239000000da0d7472616e736665725f66726f6d723600000029047250000000da0e63757272656e745f616d6f756e74da11616d6f756e745f746f5f756e7374616b65da0f616d6f756e745f746f5f7374616b65722d000000722d000000722e000000da057374616b65a30000007322000000000210010e01080116010a010e010801120108011401080108010e0110010e0112017265000000290472300000007204000000da13766f74696e675f74696d655f696e5f64617973da0b6465736372697074696f6e630400000000000000050000000400000043000000735a0000007c027400740119006b0573107402820174036a0483007d0474036a057c0464011700830101007c0074067c04640266023c007c0174067c04640366023c00640474067c04640566023c0074077c047c037c02830301007c04530029064e725a00000072300000007204000000da0f72656769737465725f616374696f6eda04747970652908722700000072180000007232000000722b00000072390000007229000000da125f5f70726f706f73616c5f64657461696c73da115f5f6d6f646966795f70726f706f73616c29057230000000720400000072660000007267000000da04705f6964722d000000722d000000722e000000da1f6372656174655f72656769737465725f616374696f6e5f70726f706f73616cb800000073100000000003100108010e010c010c010c010c01726d000000630400000000000000050000000400000043000000735a0000007c027400740119006b0573107402820174036a0483007d0474036a057c0464011700830101007c0074067c04640266023c007c0174067c04640366023c00640474067c04640566023c0074077c047c037c02830301007c04530029064e725a00000072300000007204000000da0f6f766572726964655f616374696f6e72690000002908722700000072180000007232000000722b00000072390000007229000000726a000000726b00000029057230000000720400000072660000007267000000726c000000722d000000722d000000722e000000da1f6372656174655f6f766572726964655f616374696f6e5f70726f706f73616cc500000073100000000003100108010e010c010c010c010c01726f0000002903723000000072660000007267000000630300000000000000040000000400000043000000734e0000007c017400740119006b0573107402820174036a0483007d0374036a057c0364011700830101007c0074067c03640266023c00640374067c03640466023c0074077c037c027c01830301007c03530029054e725a0000007230000000da11756e72656769737465725f616374696f6e72690000002908722700000072180000007232000000722b00000072390000007229000000726a000000726b0000002904723000000072660000007267000000726c000000722d000000722d000000722e000000da216372656174655f756e72656769737465725f616374696f6e5f70726f706f73616cd2000000730e0000000003100108010e010c010c010c01727100000029057230000000721e000000726600000072670000007220000000630500000000000000060000000400000043000000736e0000007c027400740119006b0573107402820174036a0483007d0574036a057c0564011700830101007c0074067c05640266023c007c0174067c05640366023c007c0464006b0972527c0474067c05640466023c00640574067c05640666023c0074077c057c037c02830301007c05530029074e725a0000007230000000721e0000007220000000721d00000072690000002908722700000072180000007232000000722b00000072390000007229000000726a000000726b00000029067230000000721e000000726600000072670000007220000000726c000000722d000000722d000000722e000000da186372656174655f696e7465726163745f70726f706f73616cde00000073140000000003100108010e010c010c0108010c010c010c017272000000290572300000007249000000726600000072670000007220000000630500000000000000060000000400000043000000736e0000007c027400740119006b0573107402820174036a0483007d0574036a057c0564011700830101007c0074067c05640266023c007c0174067c05640366023c007c0464006b0972527c0474067c05640466023c00640574067c05640666023c0074077c057c037c02830301007c05530029074e725a000000723000000072490000007220000000724b00000072690000002908722700000072180000007232000000722b00000072390000007229000000726a000000726b000000290672300000007249000000726600000072670000007220000000726c000000722d000000722d000000722e000000da1d6372656174655f62756c6b5f696e7465726163745f70726f706f73616ced00000073140000000003100108010e010c010c0108010c010c010c0172730000002905da0773657474696e67724d00000072660000007267000000724e00000063050000000000000006000000040000004300000073760000007c027400740119006b057310740282017c0074036b037320740264018301820174046a0583007d0574046a067c0564021700830101007c04724274077c0183017d017c0074087c05640366023c007c0174087c05640466023c00640574087c05640666023c0074097c057c037c02830301007c05530029074e7a2c4f6e6c7920746865206f776e65722063616e206368616e676520746865206f776e65722073657474696e672e725a0000007274000000724d000000da0e6368616e67655f73657474696e677269000000290a7227000000721800000072320000007217000000722b00000072390000007229000000722c000000726a000000726b00000029067274000000724d00000072660000007267000000724e000000726c000000722d000000722d000000722e000000da1e6372656174655f6368616e67655f73657474696e675f70726f706f73616cfc000000731600000000031001100108010e01040108010c010c010c010c01727600000029057223000000725000000072510000007267000000726600000063050000000000000006000000040000004300000073660000007c047400740119006b0573107402820174036a0483007d0574036a057c0564011700830101007c0074067c05640266023c007c0174067c05640366023c007c0274067c05640466023c00640574067c05640666023c0074077c057c037c04830301007c05530029074e725a00000072230000007250000000da087265636569766572725200000072690000002908722700000072180000007232000000722b00000072390000007229000000726a000000726b000000290672230000007250000000725100000072670000007266000000726c000000722d000000722d000000722e000000da186372656174655f7472616e736665725f70726f706f73616c0c01000073120000000003100108010e010c010c010c010c010c01727800000063050000000000000006000000040000004300000073660000007c047400740119006b0573107402820174036a0483007d0574036a057c0564011700830101007c0074067c05640266023c007c0174067c05640366023c007c0274067c05640466023c00640574067c05640666023c0074077c057c037c04830301007c05530029074e725a000000722300000072500000007277000000da08617070726f76616c72690000002908722700000072180000007232000000722b00000072390000007229000000726a000000726b000000290672230000007250000000725100000072670000007266000000726c000000722d000000722d000000722e000000da186372656174655f617070726f76616c5f70726f706f73616c1a01000073120000000003100108010e010c010c010c010c010c01727a0000002902726c0000007247000000630200000000000000030000000400000043000000734c0000007c0174007c0074016a0266023c0074037c00640166021900701c67007d0274016a027c026b07733074046402830182017c026a0574016a02830101007c0274037c00640166023c006400530029034eda06766f746572737a17596f75206861766520616c726561647920766f7465642e2906da055f5f73696772260000007220000000726a0000007232000000723a0000002903726c0000007247000000727b000000722d000000722d000000722e000000da04766f746528010000730a00000000020e01100112010c01727d0000002902726c000000724500000063010000000000000006000000060000004300000073b202000074007c0064016602190074016a02640264038d0174007c006404660219001400170074036b017330740464058301820174057c00190064066b09734474046407830182017c0074066a0783006b00735474048201640674057c003c0064087d0164087d02784074007c0064096602190044005d307d0374087c031900708064087d0474097c007c036602190064066b02729a7c017c0437007d017c027c0437007d0271725700740a6a0783007d057c017c05740b740c190014006b0072ca640a740d7c003c00640a53007c017c021b00740b740e19006b05900272a274007c00640b66021900640c6b029001721e740f74106a1174007c00640d66021900830174007c00640e6602190074007c00640f6602190064108d03010090016e7874007c00640b6602190064116b0290017260741274106a1174007c00640d66021900830174007c00640e6602190074007c00640f6602190064108d03010090016e3674007c00640b6602190064126b0290017292741374007c0064136602190074007c0064146602190064158d02010090016e0474007c00640b6602190064166b02900172b8741474007c0064136602190064178d0101006ede74007c00640b6602190064186b02900172e8741574007c0064136602190074007c0064146602190064158d0201006eae74007c00640b6602190064196b029002722a741674007c0064136602190074007c00641a6602190074007c00641b660219009002702274176a18641c8d0301006e6c74007c00640b66021900641d6b029002726c741974007c0064136602190074007c00641e6602190074007c00641b660219009002706474176a18641f8d0301006e2a74007c00640b6602190064206b029002729674007c00642166021900740b74007c006422660219003c006406740d7c003c0064065300640a740d7c003c00640a53006400530029234e7259000000725a0000002901725b000000da086475726174696f6e7a1250726f706f73616c206e6f74206f76657221547a1950726f706f73616c20616c7265616479207265736f6c7665647206000000727b00000046726900000072520000007223000000725000000072770000002902725000000072510000007279000000726800000072300000007204000000290272300000007204000000727000000029017230000000726e000000721d000000721e000000722000000029037230000000721e0000007220000000724b000000724900000029037230000000724900000072200000007275000000724d0000007274000000291a726a000000725e000000725f00000072600000007232000000da145f5f66696e69736865645f70726f706f73616c73722b0000007239000000725d000000727c00000072280000007227000000721a000000da085f5f73746174757372190000007254000000723300000072340000007256000000723d00000072410000007240000000724800000072260000007236000000724a0000002906726c000000da09617070726f76616c73da0b746f74616c5f766f746573da01787265000000da0671756f72756d722d000000722d000000722e000000da1164657465726d696e655f726573756c747331010000735e000000000214011c011401100108010401040112010c01100108010c010801100108010401120112010a010c011a0112010a010c011a0112010c0114011201140112010c01120112010c010a011a011201060110011a011202180108010402080172850000002901726c000000630100000000000000020000000b00000043000000736400000074007c0064016602190074007c0064026602190074007c0064036602190074007c0064046602190074007c0064056602190074007c0064066602190074007c0064076602190074007c0064086602190074007c00640966021900640a9c097d017c015300290b4e7274000000724d0000007223000000da1070726f706f73616c5f63726561746f72726700000072590000007269000000727e000000727700000029097274000000724d00000072230000007286000000726700000072590000007269000000727e00000072770000002901726a0000002902726c000000da04696e666f722d000000722d000000722e000000da1470726f706f73616c5f696e666f726d6174696f6e66010000731200000000020a010a010a010a010c0112010a01100172880000002903726c00000072670000007266000000630300000000000000030000000400000043000000733600000074006a0174027c00640166023c007c0174027c00640266023c00740374027c00640366023c007c0274027c00640466023c006400530029054e728600000072670000007259000000727e000000290472260000007220000000726a00000072600000002903726c00000072670000007266000000722d000000722d000000722e000000726b00000073010000730800000000010e010c010c01726b0000002903721e000000721f00000072200000002901722200000029014629014e29014e290146293dda09696d706f72746c69627233000000da04486173687227000000725d000000da085661726961626c657228000000722b000000727f000000727c000000726a00000072800000007216000000721700000072180000007219000000721a000000721b000000da0a5f5f6d65746164617461722a000000721f0000007231000000da0446756e637238000000da03737472722f000000723d00000072400000007241000000da085f5f6578706f7274724200000072430000007244000000da0464696374da03416e797248000000721d000000da046c697374724a000000724b000000da04626f6f6c724f000000da05666c6f617472540000007256000000725700000072580000007265000000da03696e74726d000000726f00000072710000007272000000727300000072760000007278000000727a000000727d00000072850000007288000000726b000000722d000000722d000000722d000000722e000000da083c6d6f64756c653e0100000073a80000000401060108010e020c010c01040108010e01040108010c01040104010401040104010401060108010401080106010201040102010201020108010c011003100c100d10100e0a060112060601120606011006140806011404120506011204060116081205120506011406060114060601101406010401120b06010401120b06010401100a06021a0d06021a0d06021a0e06010601120c06010601120c06011208060112340601100c