Vyper_contract
Deploy on AlchemyContract Information
The following smart contract code is not written in Solidity but in Vyper programming language. The code sets a boolean variable `is_killed` to `False`. The purpose of this code is not clear without the context of the entire contract.
More Info
# @version 0.3.1
"""
@title StableSwap
@author Curve.Fi
@license Copyright (c) Curve.Fi, 2020 - all rights reserved
"""
from vyper.interfaces import ERC20
interface CurveToken:
def totalSupply() -> uint256: view
def mint(_to: address, _value: uint256) -> bool: nonpayable
def burnFrom(_to: address, _value: uint256) -> bool: nonpayable
# Events
event TokenExchange:
buyer: indexed(address)
sold_id: int128
tokens_sold: uint256
bought_id: int128
tokens_bought: uint256
event AddLiquidity:
provider: indexed(address)
token_amounts: uint256[N_COINS]
fees: uint256[N_COINS]
invariant: uint256
token_supply: uint256
event RemoveLiquidity:
provider: indexed(address)
token_amounts: uint256[N_COINS]
fees: uint256[N_COINS]
token_supply: uint256
event RemoveLiquidityOne:
provider: indexed(address)
token_amount: uint256
coin_amount: uint256
token_supply: uint256
event RemoveLiquidityImbalance:
provider: indexed(address)
token_amounts: uint256[N_COINS]
fees: uint256[N_COINS]
invariant: uint256
token_supply: uint256
event CommitNewAdmin:
deadline: indexed(uint256)
admin: indexed(address)
event NewAdmin:
admin: indexed(address)
event CommitNewFee:
deadline: indexed(uint256)
fee: uint256
admin_fee: uint256
event NewFee:
fee: uint256
admin_fee: uint256
event RampA:
old_A: uint256
new_A: uint256
initial_time: uint256
future_time: uint256
event StopRampA:
A: uint256
t: uint256
# These constants must be set prior to compiling
N_COINS: constant(int128) = 2
PRECISION_MUL: constant(uint256[N_COINS]) = [1, 1000000000000]
RATES: constant(uint256[N_COINS]) = [1000000000000000000, 1000000000000000000000000000000]
# fixed constants
FEE_DENOMINATOR: constant(uint256) = 10 ** 10
PRECISION: constant(uint256) = 10 ** 18 # The precision to convert to
MAX_ADMIN_FEE: constant(uint256) = 10 * 10 ** 9
MAX_FEE: constant(uint256) = 5 * 10 ** 9
MAX_A: constant(uint256) = 10 ** 6
MAX_A_CHANGE: constant(uint256) = 10
ADMIN_ACTIONS_DELAY: constant(uint256) = 3 * 86400
MIN_RAMP_TIME: constant(uint256) = 86400
coins: public(address[N_COINS])
balances: public(uint256[N_COINS])
fee: public(uint256) # fee * 1e10
admin_fee: public(uint256) # admin_fee * 1e10
owner: public(address)
lp_token: public(address)
A_PRECISION: constant(uint256) = 100
initial_A: public(uint256)
future_A: public(uint256)
initial_A_time: public(uint256)
future_A_time: public(uint256)
admin_actions_deadline: public(uint256)
transfer_ownership_deadline: public(uint256)
future_fee: public(uint256)
future_admin_fee: public(uint256)
future_owner: public(address)
is_killed: bool
kill_deadline: uint256
KILL_DEADLINE_DT: constant(uint256) = 2 * 30 * 86400
@external
def __init__(
_owner: address,
_coins: address[N_COINS],
_pool_token: address,
_A: uint256,
_fee: uint256,
_admin_fee: uint256
):
"""
@notice Contract constructor
@param _owner Contract owner address
@param _coins Addresses of ERC20 conracts of coins
@param _pool_token Address of the token representing LP share
@param _A Amplification coefficient multiplied by n * (n - 1)
@param _fee Fee to charge for exchanges
@param _admin_fee Admin fee
"""
for i in range(N_COINS):
assert _coins[i] != ZERO_ADDRESS
self.coins = _coins
self.initial_A = _A * A_PRECISION
self.future_A = _A * A_PRECISION
self.fee = _fee
self.admin_fee = _admin_fee
self.owner = _owner
self.kill_deadline = block.timestamp + KILL_DEADLINE_DT
self.lp_token = _pool_token
@view
@internal
def _A() -> uint256:
"""
Handle ramping A up or down
"""
t1: uint256 = self.future_A_time
A1: uint256 = self.future_A
if block.timestamp < t1:
A0: uint256 = self.initial_A
t0: uint256 = self.initial_A_time
# Expressions in uint256 cannot have negative numbers, thus "if"
if A1 > A0:
return A0 + (A1 - A0) * (block.timestamp - t0) / (t1 - t0)
else:
return A0 - (A0 - A1) * (block.timestamp - t0) / (t1 - t0)
else: # when t1 == 0 or block.timestamp >= t1
return A1
@view
@external
def A() -> uint256:
return self._A() / A_PRECISION
@view
@external
def A_precise() -> uint256:
return self._A()
@view
@internal
def _xp() -> uint256[N_COINS]:
result: uint256[N_COINS] = RATES
for i in range(N_COINS):
result[i] = result[i] * self.balances[i] / PRECISION
return result
@pure
@internal
def _xp_mem(_balances: uint256[N_COINS]) -> uint256[N_COINS]:
result: uint256[N_COINS] = RATES
for i in range(N_COINS):
result[i] = result[i] * _balances[i] / PRECISION
return result
@pure
@internal
def _get_D(_xp: uint256[N_COINS], _amp: uint256) -> uint256:
"""
D invariant calculation in non-overflowing integer operations
iteratively
A * sum(x_i) * n**n + D = A * D * n**n + D**(n+1) / (n**n * prod(x_i))
Converging solution:
D[j+1] = (A * n**n * sum(x_i) - D[j]**(n+1) / (n**n prod(x_i))) / (A * n**n - 1)
"""
S: uint256 = 0
Dprev: uint256 = 0
for _x in _xp:
S += _x
if S == 0:
return 0
D: uint256 = S
Ann: uint256 = _amp * N_COINS
for _i in range(255):
D_P: uint256 = D
for _x in _xp:
D_P = D_P * D / (_x * N_COINS) # If division by 0, this will be borked: only withdrawal will work. And that is good
Dprev = D
D = (Ann * S / A_PRECISION + D_P * N_COINS) * D / ((Ann - A_PRECISION) * D / A_PRECISION + (N_COINS + 1) * D_P)
# Equality with the precision of 1
if D > Dprev:
if D - Dprev <= 1:
return D
else:
if Dprev - D <= 1:
return D
# convergence typically occurs in 4 rounds or less, this should be unreachable!
# if it does happen the pool is borked and LPs can withdraw via `remove_liquidity`
raise
@view
@internal
def _get_D_mem(_balances: uint256[N_COINS], _amp: uint256) -> uint256:
return self._get_D(self._xp_mem(_balances), _amp)
@view
@external
def get_virtual_price() -> uint256:
"""
@notice The current virtual price of the pool LP token
@dev Useful for calculating profits
@return LP token virtual price normalized to 1e18
"""
D: uint256 = self._get_D(self._xp(), self._A())
# D is in the units similar to DAI (e.g. converted to precision 1e18)
# When balanced, D = n * x_u - total virtual value of the portfolio
token_supply: uint256 = ERC20(self.lp_token).totalSupply()
return D * PRECISION / token_supply
@view
@external
def calc_token_amount(_amounts: uint256[N_COINS], _is_deposit: bool) -> uint256:
"""
@notice Calculate addition or reduction in token supply from a deposit or withdrawal
@dev This calculation accounts for slippage, but not fees.
Needed to prevent front-running, not for precise calculations!
@param _amounts Amount of each coin being deposited
@param _is_deposit set True for deposits, False for withdrawals
@return Expected amount of LP tokens received
"""
amp: uint256 = self._A()
balances: uint256[N_COINS] = self.balances
D0: uint256 = self._get_D_mem(balances, amp)
for i in range(N_COINS):
if _is_deposit:
balances[i] += _amounts[i]
else:
balances[i] -= _amounts[i]
D1: uint256 = self._get_D_mem(balances, amp)
token_amount: uint256 = CurveToken(self.lp_token).totalSupply()
diff: uint256 = 0
if _is_deposit:
diff = D1 - D0
else:
diff = D0 - D1
return diff * token_amount / D0
@external
@nonreentrant('lock')
def add_liquidity(_amounts: uint256[N_COINS], _min_mint_amount: uint256) -> uint256:
"""
@notice Deposit coins into the pool
@param _amounts List of amounts of coins to deposit
@param _min_mint_amount Minimum amount of LP tokens to mint from the deposit
@return Amount of LP tokens received by depositing
"""
assert not self.is_killed # dev: is killed
amp: uint256 = self._A()
old_balances: uint256[N_COINS] = self.balances
# Initial invariant
D0: uint256 = self._get_D_mem(old_balances, amp)
lp_token: address = self.lp_token
token_supply: uint256 = CurveToken(lp_token).totalSupply()
new_balances: uint256[N_COINS] = old_balances
for i in range(N_COINS):
if token_supply == 0:
assert _amounts[i] > 0 # dev: initial deposit requires all coins
# balances store amounts of c-tokens
new_balances[i] += _amounts[i]
# Invariant after change
D1: uint256 = self._get_D_mem(new_balances, amp)
assert D1 > D0
# We need to recalculate the invariant accounting for fees
# to calculate fair user's share
D2: uint256 = D1
fees: uint256[N_COINS] = empty(uint256[N_COINS])
mint_amount: uint256 = 0
if token_supply > 0:
# Only account for fees if we are not the first to deposit
fee: uint256 = self.fee * N_COINS / (4 * (N_COINS - 1))
admin_fee: uint256 = self.admin_fee
for i in range(N_COINS):
ideal_balance: uint256 = D1 * old_balances[i] / D0
difference: uint256 = 0
new_balance: uint256 = new_balances[i]
if ideal_balance > new_balance:
difference = ideal_balance - new_balance
else:
difference = new_balance - ideal_balance
fees[i] = fee * difference / FEE_DENOMINATOR
self.balances[i] = new_balance - (fees[i] * admin_fee / FEE_DENOMINATOR)
new_balances[i] -= fees[i]
D2 = self._get_D_mem(new_balances, amp)
mint_amount = token_supply * (D2 - D0) / D0
else:
self.balances = new_balances
mint_amount = D1 # Take the dust if there was any
assert mint_amount >= _min_mint_amount, "Slippage screwed you"
# Take coins from the sender
for i in range(N_COINS):
if _amounts[i] > 0:
# "safeTransferFrom" which works for ERC20s which return bool or not
_response: Bytes[32] = raw_call(
self.coins[i],
concat(
method_id("transferFrom(address,address,uint256)"),
convert(msg.sender, bytes32),
convert(self, bytes32),
convert(_amounts[i], bytes32),
),
max_outsize=32,
)
if len(_response) > 0:
assert convert(_response, bool) # dev: failed transfer
# end "safeTransferFrom"
# Mint pool tokens
CurveToken(lp_token).mint(msg.sender, mint_amount)
log AddLiquidity(msg.sender, _amounts, fees, D1, token_supply + mint_amount)
return mint_amount
@view
@internal
def _get_y(i: int128, j: int128, x: uint256, _xp: uint256[N_COINS]) -> uint256:
"""
Calculate x[j] if one makes x[i] = x
Done by solving quadratic equation iteratively.
x_1**2 + x_1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)
x_1**2 + b*x_1 = c
x_1 = (x_1**2 + c) / (2*x_1 + b)
"""
# x in the input is converted to the same price/precision
assert i != j # dev: same coin
assert j >= 0 # dev: j below zero
assert j < N_COINS # dev: j above N_COINS
# should be unreachable, but good for safety
assert i >= 0
assert i < N_COINS
A: uint256 = self._A()
D: uint256 = self._get_D(_xp, A)
Ann: uint256 = A * N_COINS
c: uint256 = D
S: uint256 = 0
_x: uint256 = 0
y_prev: uint256 = 0
for _i in range(N_COINS):
if _i == i:
_x = x
elif _i != j:
_x = _xp[_i]
else:
continue
S += _x
c = c * D / (_x * N_COINS)
c = c * D * A_PRECISION / (Ann * N_COINS)
b: uint256 = S + D * A_PRECISION / Ann # - D
y: uint256 = D
for _i in range(255):
y_prev = y
y = (y*y + c) / (2 * y + b - D)
# Equality with the precision of 1
if y > y_prev:
if y - y_prev <= 1:
return y
else:
if y_prev - y <= 1:
return y
raise
@view
@external
def get_dy(i: int128, j: int128, _dx: uint256) -> uint256:
xp: uint256[N_COINS] = self._xp()
rates: uint256[N_COINS] = RATES
x: uint256 = xp[i] + (_dx * rates[i] / PRECISION)
y: uint256 = self._get_y(i, j, x, xp)
dy: uint256 = xp[j] - y - 1
fee: uint256 = self.fee * dy / FEE_DENOMINATOR
return (dy - fee) * PRECISION / rates[j]
@external
@nonreentrant('lock')
def exchange(i: int128, j: int128, _dx: uint256, _min_dy: uint256) -> uint256:
"""
@notice Perform an exchange between two coins
@dev Index values can be found via the `coins` public getter method
@param i Index value for the coin to send
@param j Index valie of the coin to recieve
@param _dx Amount of `i` being exchanged
@param _min_dy Minimum amount of `j` to receive
@return Actual amount of `j` received
"""
assert not self.is_killed # dev: is killed
old_balances: uint256[N_COINS] = self.balances
xp: uint256[N_COINS] = self._xp_mem(old_balances)
rates: uint256[N_COINS] = RATES
x: uint256 = xp[i] + _dx * rates[i] / PRECISION
y: uint256 = self._get_y(i, j, x, xp)
dy: uint256 = xp[j] - y - 1 # -1 just in case there were some rounding errors
dy_fee: uint256 = dy * self.fee / FEE_DENOMINATOR
# Convert all to real units
dy = (dy - dy_fee) * PRECISION / rates[j]
assert dy >= _min_dy, "Exchange resulted in fewer coins than expected"
dy_admin_fee: uint256 = dy_fee * self.admin_fee / FEE_DENOMINATOR
dy_admin_fee = dy_admin_fee * PRECISION / rates[j]
# Change balances exactly in same way as we change actual ERC20 coin amounts
self.balances[i] = old_balances[i] + _dx
# When rounding errors happen, we undercharge admin fee in favor of LP
self.balances[j] = old_balances[j] - dy - dy_admin_fee
_response: Bytes[32] = raw_call(
self.coins[i],
concat(
method_id("transferFrom(address,address,uint256)"),
convert(msg.sender, bytes32),
convert(self, bytes32),
convert(_dx, bytes32),
),
max_outsize=32,
)
if len(_response) > 0:
assert convert(_response, bool)
_response = raw_call(
self.coins[j],
concat(
method_id("transfer(address,uint256)"),
convert(msg.sender, bytes32),
convert(dy, bytes32),
),
max_outsize=32,
)
if len(_response) > 0:
assert convert(_response, bool)
log TokenExchange(msg.sender, i, _dx, j, dy)
return dy
@external
@nonreentrant('lock')
def remove_liquidity(_amount: uint256, _min_amounts: uint256[N_COINS]) -> uint256[N_COINS]:
"""
@notice Withdraw coins from the pool
@dev Withdrawal amounts are based on current deposit ratios
@param _amount Quantity of LP tokens to burn in the withdrawal
@param _min_amounts Minimum amounts of underlying coins to receive
@return List of amounts of coins that were withdrawn
"""
lp_token: address = self.lp_token
total_supply: uint256 = CurveToken(lp_token).totalSupply()
amounts: uint256[N_COINS] = empty(uint256[N_COINS])
for i in range(N_COINS):
old_balance: uint256 = self.balances[i]
value: uint256 = old_balance * _amount / total_supply
assert value >= _min_amounts[i], "Withdrawal resulted in fewer coins than expected"
self.balances[i] = old_balance - value
amounts[i] = value
_response: Bytes[32] = raw_call(
self.coins[i],
concat(
method_id("transfer(address,uint256)"),
convert(msg.sender, bytes32),
convert(value, bytes32),
),
max_outsize=32,
)
if len(_response) > 0:
assert convert(_response, bool)
CurveToken(lp_token).burnFrom(msg.sender, _amount) # dev: insufficient funds
log RemoveLiquidity(msg.sender, amounts, empty(uint256[N_COINS]), total_supply - _amount)
return amounts
@external
@nonreentrant('lock')
def remove_liquidity_imbalance(_amounts: uint256[N_COINS], _max_burn_amount: uint256) -> uint256:
"""
@notice Withdraw coins from the pool in an imbalanced amount
@param _amounts List of amounts of underlying coins to withdraw
@param _max_burn_amount Maximum amount of LP token to burn in the withdrawal
@return Actual amount of the LP token burned in the withdrawal
"""
assert not self.is_killed # dev: is killed
amp: uint256 = self._A()
old_balances: uint256[N_COINS] = self.balances
D0: uint256 = self._get_D_mem(old_balances, amp)
new_balances: uint256[N_COINS] = old_balances
for i in range(N_COINS):
new_balances[i] -= _amounts[i]
D1: uint256 = self._get_D_mem(new_balances, amp)
fee: uint256 = self.fee * N_COINS / (4 * (N_COINS - 1))
admin_fee: uint256 = self.admin_fee
fees: uint256[N_COINS] = empty(uint256[N_COINS])
for i in range(N_COINS):
new_balance: uint256 = new_balances[i]
ideal_balance: uint256 = D1 * old_balances[i] / D0
difference: uint256 = 0
if ideal_balance > new_balance:
difference = ideal_balance - new_balance
else:
difference = new_balance - ideal_balance
fees[i] = fee * difference / FEE_DENOMINATOR
self.balances[i] = new_balance - (fees[i] * admin_fee / FEE_DENOMINATOR)
new_balances[i] = new_balance - fees[i]
D2: uint256 = self._get_D_mem(new_balances, amp)
lp_token: address = self.lp_token
token_supply: uint256 = CurveToken(lp_token).totalSupply()
token_amount: uint256 = (D0 - D2) * token_supply / D0
assert token_amount != 0 # dev: zero tokens burned
token_amount += 1 # In case of rounding errors - make it unfavorable for the "attacker"
assert token_amount <= _max_burn_amount, "Slippage screwed you"
CurveToken(lp_token).burnFrom(msg.sender, token_amount) # dev: insufficient funds
for i in range(N_COINS):
if _amounts[i] != 0:
_response: Bytes[32] = raw_call(
self.coins[i],
concat(
method_id("transfer(address,uint256)"),
convert(msg.sender, bytes32),
convert(_amounts[i], bytes32),
),
max_outsize=32,
)
if len(_response) > 0:
assert convert(_response, bool)
log RemoveLiquidityImbalance(msg.sender, _amounts, fees, D1, token_supply - token_amount)
return token_amount
@pure
@internal
def _get_y_D(A: uint256, i: int128, _xp: uint256[N_COINS], D: uint256) -> uint256:
"""
Calculate x[i] if one reduces D from being calculated for xp to D
Done by solving quadratic equation iteratively.
x_1**2 + x_1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)
x_1**2 + b*x_1 = c
x_1 = (x_1**2 + c) / (2*x_1 + b)
"""
# x in the input is converted to the same price/precision
assert i >= 0 # dev: i below zero
assert i < N_COINS # dev: i above N_COINS
Ann: uint256 = A * N_COINS
c: uint256 = D
S: uint256 = 0
_x: uint256 = 0
y_prev: uint256 = 0
for _i in range(N_COINS):
if _i != i:
_x = _xp[_i]
else:
continue
S += _x
c = c * D / (_x * N_COINS)
c = c * D * A_PRECISION / (Ann * N_COINS)
b: uint256 = S + D * A_PRECISION / Ann
y: uint256 = D
for _i in range(255):
y_prev = y
y = (y*y + c) / (2 * y + b - D)
# Equality with the precision of 1
if y > y_prev:
if y - y_prev <= 1:
return y
else:
if y_prev - y <= 1:
return y
raise
@view
@internal
def _calc_withdraw_one_coin(_token_amount: uint256, i: int128) -> (uint256, uint256, uint256):
# First, need to calculate
# * Get current D
# * Solve Eqn against y_i for D - _token_amount
amp: uint256 = self._A()
xp: uint256[N_COINS] = self._xp()
D0: uint256 = self._get_D(xp, amp)
total_supply: uint256 = CurveToken(self.lp_token).totalSupply()
D1: uint256 = D0 - _token_amount * D0 / total_supply
new_y: uint256 = self._get_y_D(amp, i, xp, D1)
xp_reduced: uint256[N_COINS] = xp
fee: uint256 = self.fee * N_COINS / (4 * (N_COINS - 1))
for j in range(N_COINS):
dx_expected: uint256 = 0
if j == i:
dx_expected = xp[j] * D1 / D0 - new_y
else:
dx_expected = xp[j] - xp[j] * D1 / D0
xp_reduced[j] -= fee * dx_expected / FEE_DENOMINATOR
dy: uint256 = xp_reduced[i] - self._get_y_D(amp, i, xp_reduced, D1)
precisions: uint256[N_COINS] = PRECISION_MUL
dy = (dy - 1) / precisions[i] # Withdraw less to account for rounding errors
dy_0: uint256 = (xp[i] - new_y) / precisions[i] # w/o fees
return dy, dy_0 - dy, total_supply
@view
@external
def calc_withdraw_one_coin(_token_amount: uint256, i: int128) -> uint256:
"""
@notice Calculate the amount received when withdrawing a single coin
@param _token_amount Amount of LP tokens to burn in the withdrawal
@param i Index value of the coin to withdraw
@return Amount of coin received
"""
return self._calc_withdraw_one_coin(_token_amount, i)[0]
@external
@nonreentrant('lock')
def remove_liquidity_one_coin(_token_amount: uint256, i: int128, _min_amount: uint256) -> uint256:
"""
@notice Withdraw a single coin from the pool
@param _token_amount Amount of LP tokens to burn in the withdrawal
@param i Index value of the coin to withdraw
@param _min_amount Minimum amount of coin to receive
@return Amount of coin received
"""
assert not self.is_killed # dev: is killed
dy: uint256 = 0
dy_fee: uint256 = 0
total_supply: uint256 = 0
dy, dy_fee, total_supply = self._calc_withdraw_one_coin(_token_amount, i)
assert dy >= _min_amount, "Not enough coins removed"
self.balances[i] -= (dy + dy_fee * self.admin_fee / FEE_DENOMINATOR)
CurveToken(self.lp_token).burnFrom(msg.sender, _token_amount) # dev: insufficient funds
_response: Bytes[32] = raw_call(
self.coins[i],
concat(
method_id("transfer(address,uint256)"),
convert(msg.sender, bytes32),
convert(dy, bytes32),
),
max_outsize=32,
)
if len(_response) > 0:
assert convert(_response, bool)
log RemoveLiquidityOne(msg.sender, _token_amount, dy, total_supply - _token_amount)
return dy
### Admin functions ###
@external
def ramp_A(_future_A: uint256, _future_time: uint256):
assert msg.sender == self.owner # dev: only owner
assert block.timestamp >= self.initial_A_time + MIN_RAMP_TIME
assert _future_time >= block.timestamp + MIN_RAMP_TIME # dev: insufficient time
initial_A: uint256 = self._A()
future_A_p: uint256 = _future_A * A_PRECISION
assert _future_A > 0 and _future_A < MAX_A
if future_A_p < initial_A:
assert future_A_p * MAX_A_CHANGE >= initial_A
else:
assert future_A_p <= initial_A * MAX_A_CHANGE
self.initial_A = initial_A
self.future_A = future_A_p
self.initial_A_time = block.timestamp
self.future_A_time = _future_time
log RampA(initial_A, future_A_p, block.timestamp, _future_time)
@external
def stop_ramp_A():
assert msg.sender == self.owner # dev: only owner
current_A: uint256 = self._A()
self.initial_A = current_A
self.future_A = current_A
self.initial_A_time = block.timestamp
self.future_A_time = block.timestamp
# now (block.timestamp < t1) is always False, so we return saved A
log StopRampA(current_A, block.timestamp)
@external
def commit_new_fee(_new_fee: uint256, _new_admin_fee: uint256):
assert msg.sender == self.owner # dev: only owner
assert self.admin_actions_deadline == 0 # dev: active action
assert _new_fee <= MAX_FEE # dev: fee exceeds maximum
assert _new_admin_fee <= MAX_ADMIN_FEE # dev: admin fee exceeds maximum
deadline: uint256 = block.timestamp + ADMIN_ACTIONS_DELAY
self.admin_actions_deadline = deadline
self.future_fee = _new_fee
self.future_admin_fee = _new_admin_fee
log CommitNewFee(deadline, _new_fee, _new_admin_fee)
@external
def apply_new_fee():
assert msg.sender == self.owner # dev: only owner
assert block.timestamp >= self.admin_actions_deadline # dev: insufficient time
assert self.admin_actions_deadline != 0 # dev: no active action
self.admin_actions_deadline = 0
fee: uint256 = self.future_fee
admin_fee: uint256 = self.future_admin_fee
self.fee = fee
self.admin_fee = admin_fee
log NewFee(fee, admin_fee)
@external
def revert_new_parameters():
assert msg.sender == self.owner # dev: only owner
self.admin_actions_deadline = 0
@external
def commit_transfer_ownership(_owner: address):
assert msg.sender == self.owner # dev: only owner
assert self.transfer_ownership_deadline == 0 # dev: active transfer
deadline: uint256 = block.timestamp + ADMIN_ACTIONS_DELAY
self.transfer_ownership_deadline = deadline
self.future_owner = _owner
log CommitNewAdmin(deadline, _owner)
@external
def apply_transfer_ownership():
assert msg.sender == self.owner # dev: only owner
assert block.timestamp >= self.transfer_ownership_deadline # dev: insufficient time
assert self.transfer_ownership_deadline != 0 # dev: no active transfer
self.transfer_ownership_deadline = 0
owner: address = self.future_owner
self.owner = owner
log NewAdmin(owner)
@external
def revert_transfer_ownership():
assert msg.sender == self.owner # dev: only owner
self.transfer_ownership_deadline = 0
@view
@external
def admin_balances(i: uint256) -> uint256:
return ERC20(self.coins[i]).balanceOf(self) - self.balances[i]
@external
def withdraw_admin_fees():
assert msg.sender == self.owner # dev: only owner
for i in range(N_COINS):
coin: address = self.coins[i]
value: uint256 = ERC20(coin).balanceOf(self) - self.balances[i]
if value > 0:
_response: Bytes[32] = raw_call(
coin,
concat(
method_id("transfer(address,uint256)"),
convert(msg.sender, bytes32),
convert(value, bytes32),
),
max_outsize=32,
) # dev: failed transfer
if len(_response) > 0:
assert convert(_response, bool)
@external
def donate_admin_fees():
assert msg.sender == self.owner # dev: only owner
for i in range(N_COINS):
self.balances[i] = ERC20(self.coins[i]).balanceOf(self)
@external
def kill_me():
assert msg.sender == self.owner # dev: only owner
assert self.kill_deadline > block.timestamp # dev: deadline has passed
self.is_killed = True
@external
def unkill_me():
assert msg.sender == self.owner # dev: only owner
self.is_killed = False
[{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[2]","indexed":false},{"name":"fees","type":"uint256[2]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[2]","indexed":false},{"name":"fees","type":"uint256[2]","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amount","type":"uint256","indexed":false},{"name":"coin_amount","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityImbalance","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[2]","indexed":false},{"name":"fees","type":"uint256[2]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"CommitNewAdmin","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"admin","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"NewAdmin","inputs":[{"name":"admin","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"CommitNewFee","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"fee","type":"uint256","indexed":false},{"name":"admin_fee","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewFee","inputs":[{"name":"fee","type":"uint256","indexed":false},{"name":"admin_fee","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampA","inputs":[{"name":"old_A","type":"uint256","indexed":false},{"name":"new_A","type":"uint256","indexed":false},{"name":"initial_time","type":"uint256","indexed":false},{"name":"future_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"name":"A","type":"uint256","indexed":false},{"name":"t","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_owner","type":"address"},{"name":"_coins","type":"address[2]"},{"name":"_pool_token","type":"address"},{"name":"_A","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_admin_fee","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":10058},{"stateMutability":"view","type":"function","name":"A_precise","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":10058},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":804988},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"_amounts","type":"uint256[2]"},{"name":"_is_deposit","type":"bool"}],"outputs":[{"name":"","type":"uint256"}],"gas":1593467},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[2]"},{"name":"_min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":2546841},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":1149036},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":1307513},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[2]"}],"outputs":[{"name":"","type":"uint256[2]"}],"gas":169716},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[2]"},{"name":"_max_burn_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":2546560},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"_token_amount","type":"uint256"},{"name":"i","type":"int128"}],"outputs":[{"name":"","type":"uint256"}],"gas":989},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_token_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":1620521},{"stateMutability":"nonpayable","type":"function","name":"ramp_A","inputs":[{"name":"_future_A","type":"uint256"},{"name":"_future_time","type":"uint256"}],"outputs":[],"gas":158394},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A","inputs":[],"outputs":[],"gas":154617},{"stateMutability":"nonpayable","type":"function","name":"commit_new_fee","inputs":[{"name":"_new_fee","type":"uint256"},{"name":"_new_admin_fee","type":"uint256"}],"outputs":[],"gas":113298},{"stateMutability":"nonpayable","type":"function","name":"apply_new_fee","inputs":[],"outputs":[],"gas":103621},{"stateMutability":"nonpayable","type":"function","name":"revert_new_parameters","inputs":[],"outputs":[],"gas":22901},{"stateMutability":"nonpayable","type":"function","name":"commit_transfer_ownership","inputs":[{"name":"_owner","type":"address"}],"outputs":[],"gas":78536},{"stateMutability":"nonpayable","type":"function","name":"apply_transfer_ownership","inputs":[],"outputs":[],"gas":66804},{"stateMutability":"nonpayable","type":"function","name":"revert_transfer_ownership","inputs":[],"outputs":[],"gas":22991},{"stateMutability":"view","type":"function","name":"admin_balances","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":7769},{"stateMutability":"nonpayable","type":"function","name":"withdraw_admin_fees","inputs":[],"outputs":[],"gas":31496},{"stateMutability":"nonpayable","type":"function","name":"donate_admin_fees","inputs":[],"outputs":[],"gas":82442},{"stateMutability":"nonpayable","type":"function","name":"kill_me","inputs":[],"outputs":[],"gas":40304},{"stateMutability":"nonpayable","type":"function","name":"unkill_me","inputs":[],"outputs":[],"gas":23141},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}],"gas":3225},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":3255},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3240},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3270},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3300},{"stateMutability":"view","type":"function","name":"lp_token","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3330},{"stateMutability":"view","type":"function","name":"initial_A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3360},{"stateMutability":"view","type":"function","name":"future_A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3390},{"stateMutability":"view","type":"function","name":"initial_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3420},{"stateMutability":"view","type":"function","name":"future_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3450},{"stateMutability":"view","type":"function","name":"admin_actions_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3480},{"stateMutability":"view","type":"function","name":"transfer_ownership_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3510},{"stateMutability":"view","type":"function","name":"future_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3540},{"stateMutability":"view","type":"function","name":"future_admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3570},{"stateMutability":"view","type":"function","name":"future_owner","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3600}]
[{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[2]","indexed":false},{"name":"fees","type":"uint256[2]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[2]","indexed":false},{"name":"fees","type":"uint256[2]","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amount","type":"uint256","indexed":false},{"name":"coin_amount","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityImbalance","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[2]","indexed":false},{"name":"fees","type":"uint256[2]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"CommitNewAdmin","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"admin","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"NewAdmin","inputs":[{"name":"admin","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"CommitNewFee","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"fee","type":"uint256","indexed":false},{"name":"admin_fee","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewFee","inputs":[{"name":"fee","type":"uint256","indexed":false},{"name":"admin_fee","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampA","inputs":[{"name":"old_A","type":"uint256","indexed":false},{"name":"new_A","type":"uint256","indexed":false},{"name":"initial_time","type":"uint256","indexed":false},{"name":"future_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"name":"A","type":"uint256","indexed":false},{"name":"t","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_owner","type":"address"},{"name":"_coins","type":"address[2]"},{"name":"_pool_token","type":"address"},{"name":"_A","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_admin_fee","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":10058},{"stateMutability":"view","type":"function","name":"A_precise","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":10058},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":804988},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"_amounts","type":"uint256[2]"},{"name":"_is_deposit","type":"bool"}],"outputs":[{"name":"","type":"uint256"}],"gas":1593467},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[2]"},{"name":"_min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":2546841},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":1149036},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"_dx","type":"uint256"},{"name":"_min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":1307513},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[2]"}],"outputs":[{"name":"","type":"uint256[2]"}],"gas":169716},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[2]"},{"name":"_max_burn_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":2546560},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"_token_amount","type":"uint256"},{"name":"i","type":"int128"}],"outputs":[{"name":"","type":"uint256"}],"gas":989},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_token_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":1620521},{"stateMutability":"nonpayable","type":"function","name":"ramp_A","inputs":[{"name":"_future_A","type":"uint256"},{"name":"_future_time","type":"uint256"}],"outputs":[],"gas":158394},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A","inputs":[],"outputs":[],"gas":154617},{"stateMutability":"nonpayable","type":"function","name":"commit_new_fee","inputs":[{"name":"_new_fee","type":"uint256"},{"name":"_new_admin_fee","type":"uint256"}],"outputs":[],"gas":113298},{"stateMutability":"nonpayable","type":"function","name":"apply_new_fee","inputs":[],"outputs":[],"gas":103621},{"stateMutability":"nonpayable","type":"function","name":"revert_new_parameters","inputs":[],"outputs":[],"gas":22901},{"stateMutability":"nonpayable","type":"function","name":"commit_transfer_ownership","inputs":[{"name":"_owner","type":"address"}],"outputs":[],"gas":78536},{"stateMutability":"nonpayable","type":"function","name":"apply_transfer_ownership","inputs":[],"outputs":[],"gas":66804},{"stateMutability":"nonpayable","type":"function","name":"revert_transfer_ownership","inputs":[],"outputs":[],"gas":22991},{"stateMutability":"view","type":"function","name":"admin_balances","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":7769},{"stateMutability":"nonpayable","type":"function","name":"withdraw_admin_fees","inputs":[],"outputs":[],"gas":31496},{"stateMutability":"nonpayable","type":"function","name":"donate_admin_fees","inputs":[],"outputs":[],"gas":82442},{"stateMutability":"nonpayable","type":"function","name":"kill_me","inputs":[],"outputs":[],"gas":40304},{"stateMutability":"nonpayable","type":"function","name":"unkill_me","inputs":[],"outputs":[],"gas":23141},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}],"gas":3225},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":3255},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3240},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3270},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3300},{"stateMutability":"view","type":"function","name":"lp_token","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3330},{"stateMutability":"view","type":"function","name":"initial_A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3360},{"stateMutability":"view","type":"function","name":"future_A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3390},{"stateMutability":"view","type":"function","name":"initial_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3420},{"stateMutability":"view","type":"function","name":"future_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3450},{"stateMutability":"view","type":"function","name":"admin_actions_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3480},{"stateMutability":"view","type":"function","name":"transfer_ownership_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3510},{"stateMutability":"view","type":"function","name":"future_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3540},{"stateMutability":"view","type":"function","name":"future_admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3570},{"stateMutability":"view","type":"function","name":"future_owner","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3600}]
60206136ee6080396080518060a01c6136e95760e05260206136ee016020816080396080518060a01c6136e957610100526020602082016080396080518060a01c6136e9576101205250602060606136ee016080396080518060a01c6136e9576101405261016060006002818352015b60006101006101605160028110156136e9576020020151146136e957815160010180835281141561006f5750506101005160015561012051600255602060806136ee0160803960805160648082028215828483041417156136e95790509050600955602060806136ee0160803960805160648082028215828483041417156136e95790509050600a55602060a06136ee01608039608051600555602060c06136ee0160803960805160065560e05160075542624f1a0081818301106136e95780820190509050601355610140516008556136d156600436101561000d57612698565b60046000601c37600051346135885763f446c1d0811861004a5761003261016061269e565b61016051606480820490509050610180526020610180f35b6376a2f0f0811861006f5761006061016061269e565b61016051610180526020610180f35b63bb7b8b80811861014a576100856102606127d9565b61026080516102e052806020015161030052506100a36102a061269e565b6102a051610320526102e05160e052610300516101005261032051610120526100cd6102c0612935565b6102c051610240526318160ddd610280526020610280600461029c6008545afa6100fc573d600060003e3d6000fd5b601f3d111561358857610280516102605261024051670de0b6b3a764000080820282158284830414171561358857905090506102605180801561358857820490509050610280526020610280f35b63ed8e84f38118610324576044358060011c613588576103605261016f6103a061269e565b6103a051610380526003546103a0526004546103c0526103a051610240526103c0516102605261038051610280526101a8610400612ba2565b610400516103e05261040060006002818352015b610360516101fb576103a06104005160028110156135885760200201805160206104005102600401358082106135885780820390509050815250610230565b6103a0610400516002811015613588576020020180516020610400510260040135818183011061358857808201905090508152505b81516001018083528114156101bc5750506103a051610240526103c051610260526103805161028052610264610420612ba2565b61042051610400526318160ddd610440526020610440600461045c6008545afa610293573d600060003e3d6000fd5b601f3d1115613588576104405161042052600061044052610360516102d1576103e051610400518082106135885780820390509050610440526102ec565b610400516103e0518082106135885780820390509050610440525b610440516104205180820282158284830414171561358857905090506103e05180801561358857820490509050610460526020610460f35b630b4c7e4d8118610983576000546135885760016000556012546135885761034d61038061269e565b6103805161036052600354610380526004546103a05261038051610240526103a0516102605261036051610280526103866103e0612ba2565b6103e0516103c0526008546103e0526318160ddd610420526020610420600461043c6103e0515afa6103bd573d600060003e3d6000fd5b601f3d111561358857610420516104005261038051610420526103a0516104405261046060006002818352015b6104005161040657600060206104605102600401351115613588575b6104206104605160028110156135885760200201805160206104605102600401358181830110613588578082019050905081525081516001018083528114156103ea57505061042051610240526104405161026052610360516102805261046e610480612ba2565b61048051610460526103c0516104605111156135885761046051610480526060366104a037600061040051116104b9576104205160035561044051600455610460516104e0526106f4565b60055460028082028215828483041417156135885790509050600480820490509050610500526006546105205261054060006002818352015b6104605161038061054051600281101561358857602002015180820282158284830414171561358857905090506103c05180801561358857820490509050610560526000610580526104206105405160028110156135885760200201516105a0526105a051610560511161057f576105a0516105605180821061358857808203905090506105805261059a565b610560516105a0518082106135885780820390509050610580525b610500516105805180820282158284830414171561358857905090506402540be400808204905090506104a06105405160028110156135885760200201526105a0516104a06105405160028110156135885760200201516105205180820282158284830414171561358857905090506402540be4008082049050905080821061358857808203905090506001610540516002811015613588570260030155610420610540516002811015613588576020020180516104a0610540516002811015613588576020020151808210613588578082039050905081525081516001018083528114156104f25750506104205161024052610440516102605261036051610280526106a8610540612ba2565b610540516104805261040051610480516103c051808210613588578082039050905080820282158284830414171561358857905090506103c051808015613588578204905090506104e0525b6044356104e0511015610778576014610500527f536c697070616765207363726577656420796f750000000000000000000000006105205261050050610500518061052001818260206001820306601f82010390500336823750506308c379a06104c05260206104e0526105005160206001820306601f82010390506044016104dcfd5b61050060006002818352015b6000602061050051026004013511156108b05760006004610560527f23b872dd00000000000000000000000000000000000000000000000000000000610580526105606004806020846105a00101826020850160045afa505080518201915050336020826105a0010152602081019050306020826105a001015260208101905060206105005102600401356020826105a0010152602081019050806105a0526105a0505060206106606105a0516105c0600060016105005160028110156135885702600101545af161085b573d600060003e3d6000fd5b61064060203d80821161086e5781610870565b805b905090508152805160200180610520828460045afa9050505060006105205111156108b057610540516105205181816020036008021c9050905015613588575b81516001018083528114156107845750506340c10f196105005233610520526104e051610540526020610500604461051c60006103e0515af16108f8573d600060003e3d6000fd5b601f3d11156135885761050050337f26f55a85081d24974e85c6c00045d0f0453991e95873f52bff0d21af4079a76860043561050052602435610520526104a051610540526104c051610560526104605161058052610400516104e051818183011061358857808201905090506105a05260c0610500a26104e0516105005260206105006000600055f35b635e0d443f8118610b5a576004358060801d81607f1d1861358857610420526024358060801d81607f1d1861358857610440526109c16104a06127d9565b6104a080516104605280602001516104805250670de0b6b3a76400006104a0526c0c9f2c9cd04674edea400000006104c0526104606104205160028110156135885760200201516044356104a06104205160028110156135885760200201518082028215828483041417156135885790509050670de0b6b3a764000080820490509050818183011061358857808201905090506104e052610420516102405261044051610260526104e05161028052610460516102a052610480516102c052610a8b610520612c02565b610520516105005261046061044051600281101561358857602002015161050051808210613588578082039050905060018082106135885780820390509050610520526005546105205180820282158284830414171561358857905090506402540be400808204905090506105405261052051610540518082106135885780820390509050670de0b6b3a764000080820282158284830414171561358857905090506104a061044051600281101561358857602002015180801561358857820490509050610560526020610560f35b633df02124811861116d576004358060801d81607f1d1861358857610420526024358060801d81607f1d1861358857610440526000546135885760016000556012546135885760035461046052600454610480526104605160e0526104805161010052610bc86104e0612885565b6104e080516104a05280602001516104c05250670de0b6b3a76400006104e0526c0c9f2c9cd04674edea40000000610500526104a06104205160028110156135885760200201516044356104e06104205160028110156135885760200201518082028215828483041417156135885790509050670de0b6b3a76400008082049050905081818301106135885780820190509050610520526104205161024052610440516102605261052051610280526104a0516102a0526104c0516102c052610c92610560612c02565b61056051610540526104a061044051600281101561358857602002015161054051808210613588578082039050905060018082106135885780820390509050610560526105605160055480820282158284830414171561358857905090506402540be400808204905090506105805261056051610580518082106135885780820390509050670de0b6b3a764000080820282158284830414171561358857905090506104e06104405160028110156135885760200201518080156135885782049050905061056052606435610560511015610e0357602e6105a0527f45786368616e676520726573756c74656420696e20666577657220636f696e736105c0527f207468616e2065787065637465640000000000000000000000000000000000006105e0526105a0506105a051806105c001818260206001820306601f82010390500336823750506308c379a0610560526020610580526105a05160206001820306601f820103905060440161057cfd5b6105805160065480820282158284830414171561358857905090506402540be400808204905090506105a0526105a051670de0b6b3a764000080820282158284830414171561358857905090506104e0610440516002811015613588576020020151808015613588578204905090506105a0526104606104205160028110156135885760200201516044358181830110613588578082019050905060016104205160028110156135885702600301556104606104405160028110156135885760200201516105605180821061358857808203905090506105a0518082106135885780820390509050600161044051600281101561358857026003015560006004610600527f23b872dd00000000000000000000000000000000000000000000000000000000610620526106006004806020846106400101826020850160045afa505080518201915050336020826106400101526020810190503060208261064001015260208101905060443560208261064001015260208101905080610640526106405050602061070061064051610660600060016104205160028110156135885702600101545af1610fbb573d600060003e3d6000fd5b6106e060203d808211610fce5781610fd0565b805b9050905081528051602001806105c0828460045afa9050505060006105c0511115611010576105e0516105c05181816020036008021c9050905015613588575b60006004610600527fa9059cbb00000000000000000000000000000000000000000000000000000000610620526106006004806020846106400101826020850160045afa50508051820191505033602082610640010152602081019050610560516020826106400101526020810190508061064052610640505060206106e061064051610660600060016104405160028110156135885702600101545af16110bd573d600060003e3d6000fd5b6106c060203d8082116110d057816110d2565b805b9050905081528051602001806105c0828460045afa9050505060006105c0511115611112576105e0516105c05181816020036008021c9050905015613588575b337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd97140610420516106005260443561062052610440516106405261056051610660526080610600a2610560516106005260206106006000600055f35b635b36389c81186114da5760005461358857600160005560085460e0526318160ddd610120526020610120600461013c60e0515afa6111b1573d600060003e3d6000fd5b601f3d11156135885761012051610100526040366101203761016060006002818352015b60016101605160028110156135885702600301546101805261018051600435808202821582848304141715613588579050905061010051808015613588578204905090506101a05260206101605102602401356101a05110156112ce5760306101c0527f5769746864726177616c20726573756c74656420696e20666577657220636f696101e0527f6e73207468616e20657870656374656400000000000000000000000000000000610200526101c0506101c051806101e001818260206001820306601f82010390500336823750506308c379a06101805260206101a0526101c05160206001820306601f820103905060440161019cfd5b610180516101a051808210613588578082039050905060016101605160028110156135885702600301556101a05161012061016051600281101561358857602002015260006004610200527fa9059cbb00000000000000000000000000000000000000000000000000000000610220526102006004806020846102400101826020850160045afa505080518201915050336020826102400101526020810190506101a0516020826102400101526020810190508061024052610240505060206102e061024051610260600060016101605160028110156135885702600101545af16113be573d600060003e3d6000fd5b6102c060203d8082116113d157816113d3565b805b9050905081528051602001806101c0828460045afa9050505060006101c0511115611413576101e0516101c05181816020036008021c9050905015613588575b81516001018083528114156111d55750506379cc67906101605233610180526004356101a0526020610160604461017c600060e0515af1611459573d600060003e3d6000fd5b601f3d11156135885761016050337f7c363854ccf79623411f8995b362bce5eddff18c927edc6f5dbbb5e05819a82c610120516101605261014051610180526040366101a0376101005160043580821061358857808203905090506101e05260a0610160a26101205161016052610140516101805260406101606000600055f35b63e31032738118611af0576000546135885760016000556012546135885761150361038061269e565b6103805161036052600354610380526004546103a05261038051610240526103a05161026052610360516102805261153c6103e0612ba2565b6103e0516103c052610380516103e0526103a0516104005261042060006002818352015b6103e0610420516002811015613588576020020180516020610420510260040135808210613588578082039050905081525081516001018083528114156115605750506103e05161024052610400516102605261036051610280526115c6610440612ba2565b6104405161042052600554600280820282158284830414171561358857905090506004808204905090506104405260065461046052604036610480376104c060006002818352015b6103e06104c05160028110156135885760200201516104e052610420516103806104c051600281101561358857602002015180820282158284830414171561358857905090506103c05180801561358857820490509050610500526000610520526104e051610500511161169b576104e051610500518082106135885780820390509050610520526116b6565b610500516104e0518082106135885780820390509050610520525b610440516105205180820282158284830414171561358857905090506402540be400808204905090506104806104c05160028110156135885760200201526104e0516104806104c05160028110156135885760200201516104605180820282158284830414171561358857905090506402540be40080820490509050808210613588578082039050905060016104c05160028110156135885702600301556104e0516104806104c051600281101561358857602002015180821061358857808203905090506103e06104c0516002811015613588576020020152815160010180835281141561160e5750506103e05161024052610400516102605261036051610280526117c46104e0612ba2565b6104e0516104c0526008546104e0526318160ddd610520526020610520600461053c6104e0515afa6117fb573d600060003e3d6000fd5b601f3d11156135885761052051610500526103c0516104c05180821061358857808203905090506105005180820282158284830414171561358857905090506103c0518080156135885782049050905061052052600061052051146135885761052080516001818183011061358857808201905090508152506044356105205111156118f8576014610540527f536c697070616765207363726577656420796f750000000000000000000000006105605261054050610540518061056001818260206001820306601f82010390500336823750506308c379a0610500526020610520526105405160206001820306601f820103905060440161051cfd5b6379cc679061054052336105605261052051610580526020610540604461055c60006104e0515af161192f573d600060003e3d6000fd5b601f3d1115613588576105405061054060006002818352015b6000602061054051026004013514611a6357600060046105a0527fa9059cbb000000000000000000000000000000000000000000000000000000006105c0526105a06004806020846105e00101826020850160045afa505080518201915050336020826105e001015260208101905060206105405102600401356020826105e0010152602081019050806105e0526105e0505060206106806105e051610600600060016105405160028110156135885702600101545af1611a0e573d600060003e3d6000fd5b61066060203d808211611a215781611a23565b805b905090508152805160200180610560828460045afa905050506000610560511115611a6357610580516105605181816020036008021c9050905015613588575b8151600101808352811415611948575050337f2b5508378d7e19e0d5fa338419034731416c4f5b219a10379956f764317fd47e600435610540526024356105605261048051610580526104a0516105a052610420516105c052610500516105205180821061358857808203905090506105e05260c0610540a2610520516105405260206105406000600055f35b63cc2b27d78118611b38576024358060801d81607f1d18613588576104805260043561028052610480516102a052611b296104a06131e2565b6104a051610500526020610500f35b631a4d01d28118611e35576024358060801d81607f1d186135885761048052600054613588576001600055601254613588576060366104a03760043561028052610480516102a052611b8b6105006131e2565b61050080516104a05260208101516104c05260408101516104e052506044356104a0511015611c2b576018610500527f4e6f7420656e6f75676820636f696e732072656d6f76656400000000000000006105205261050050610500518061052001818260206001820306601f82010390500336823750506308c379a06104c05260206104e0526105005160206001820306601f82010390506044016104dcfd5b6001610480516002811015613588570260030180546104a0516104c05160065480820282158284830414171561358857905090506402540be400808204905090508181830110613588578082019050905080821061358857808203905090508155506379cc6790610500523361052052600435610540526020610500604461051c60006008545af1611cc2573d600060003e3d6000fd5b601f3d1115613588576105005060006004610540527fa9059cbb00000000000000000000000000000000000000000000000000000000610560526105406004806020846105800101826020850160045afa505080518201915050336020826105800101526020810190506104a051602082610580010152602081019050806105805261058050506020610620610580516105a0600060016104805160028110156135885702600101545af1611d7c573d600060003e3d6000fd5b61060060203d808211611d8f5781611d91565b805b905090508152805160200180610500828460045afa905050506000610500511115611dd157610520516105005181816020036008021c9050905015613588575b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a0600435610540526104a051610560526104e0516004358082106135885780820390509050610580526060610540a26104a0516105405260206105406000600055f35b633c157e648118611f8857600754331861358857600b5462015180818183011061358857808201905090504210613588574262015180818183011061358857808201905090506024351061358857611e8e61018061269e565b61018051610160526004356064808202821582848304141715613588579050905061018052600060043511611ec4576000611ecd565b620f4240600435105b1561358857610160516101805110611f075761016051600a8082028215828483041417156135885790509050610180511161358857611f2b565b6101605161018051600a808202821582848304141715613588579050905010613588575b6101605160095561018051600a5542600b55602435600c557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c254610160516101a052610180516101c052426101e0526024356102005260806101a0a1005b63551a65888118611ffb57600754331861358857611fa761018061269e565b61018051610160526101605160095561016051600a5542600b5542600c557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc2019386101605161018052426101a0526040610180a1005b635b5a1467811861209657600754331861358857600d546135885764012a05f20060043511613588576402540be4006024351161358857426203f4808181830110613588578082019050905060e05260e051600d55600435600f5560243560105560e0517f351fc5da2fbf480f2225debf3664a4bc90fa9923743aad58b4603f648e931fe060043561010052602435610120526040610100a2005b634f12fe97811861211457600754331861358857600d544210613588576000600d5414613588576000600d55600f5460e0526010546101005260e051600555610100516006557fbe12859b636aed607d5230b2cc2711f68d70e51060e6cca1f575ef5d2fcc95d160e0516101205261010051610140526040610120a1005b63226840fb811861212f576007543318613588576000600d55005b636b441a4081186121ae576004358060a01c6135885760e052600754331861358857600e5461358857426203f480818183011061358857808201905090506101005261010051600e5560e05160115560e051610100517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb9356000610120a3005b636a1c05ae811861221257600754331861358857600e544210613588576000600e5414613588576000600e5560115460e05260e05160075560e0517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c6000610100a2005b6386fbf193811861222d576007543318613588576000600e55005b63e2e7d26481186122a9576370a0823160e0523061010052602060e0602460fc600160043560028110156135885702600101545afa612271573d600060003e3d6000fd5b601f3d11156135885760e051600160043560028110156135885702600301548082106135885780820390509050610120526020610120f35b6330c54085811861244f5760075433186135885760e060006002818352015b600160e0516002811015613588570260010154610100526370a082316101405230610160526020610140602461015c610100515afa61230c573d600060003e3d6000fd5b601f3d11156135885761014051600160e0516002811015613588570260030154808210613588578082039050905061012052600061012051111561243c5760006004610180527fa9059cbb000000000000000000000000000000000000000000000000000000006101a0526101806004806020846101c00101826020850160045afa505080518201915050336020826101c0010152602081019050610120516020826101c0010152602081019050806101c0526101c0505060206102606101c0516101e06000610100515af16123e7573d600060003e3d6000fd5b61024060203d8082116123fa57816123fc565b805b905090508152805160200180610140828460045afa90505050600061014051111561243c57610160516101405181816020036008021c9050905015613588575b81516001018083528114156122c8575050005b63524c390181186124dd5760075433186135885760e060006002818352015b6370a082316101005230610120526020610100602461011c600160e05160028110156135885702600101545afa6124aa573d600060003e3d6000fd5b601f3d11156135885761010051600160e0516002811015613588570260030155815160010180835281141561246e575050005b63e3698853811861250257600754331861358857426013541115613588576001601255005b633046f972811861251d576007543318613588576000601255005b63c66106578118612544576001600435600281101561358857026001015460e052602060e0f35b634903b0d1811861256b576001600435600281101561358857026003015460e052602060e0f35b63ddca3f4381186125825760055460e052602060e0f35b63fee3f7f981186125995760065460e052602060e0f35b638da5cb5b81186125b05760075460e052602060e0f35b6382c6306681186125c75760085460e052602060e0f35b635409491a81186125de5760095460e052602060e0f35b63b4b577ad81186125f557600a5460e052602060e0f35b632081066c811861260c57600b5460e052602060e0f35b6314052288811861262357600c5460e052602060e0f35b63405e28f8811861263a57600d5460e052602060e0f35b63e0a0b586811861265157600e5460e052602060e0f35b6358680d0b811861266857600f5460e052602060e0f35b63e3824462811861267f5760105460e052602060e0f35b631ec0cdc181186126965760115460e052602060e0f35b505b60006000fd5b600c5460e052600a546101005260e05142106126c457610100518152506127d7566127d7565b60095461012052600b546101405261012051610100511161275c57610120516101205161010051808210613588578082039050905042610140518082106135885780820390509050808202821582848304141715613588579050905060e0516101405180821061358857808203905090508080156135885782049050905080821061358857808203905090508152506127d7566127d7565b610120516101005161012051808210613588578082039050905042610140518082106135885780820390509050808202821582848304141715613588579050905060e05161014051808210613588578082039050905080801561358857820490509050818183011061358857808201905090508152506127d7565b565b670de0b6b3a764000060e0526c0c9f2c9cd04674edea400000006101005261012060006002818352015b60e061012051600281101561358857602002015160016101205160028110156135885702600301548082028215828483041417156135885790509050670de0b6b3a76400008082049050905060e0610120516002811015613588576020020152815160010180835281141561280357505060e051815261010051816020015250565b670de0b6b3a7640000610120526c0c9f2c9cd04674edea400000006101405261016060006002818352015b61012061016051600281101561358857602002015160e06101605160028110156135885760200201518082028215828483041417156135885790509050670de0b6b3a76400008082049050905061012061016051600281101561358857602002015281516001018083528114156128b057505061012051815261014051816020015250565b604036610140376101a060006002818352015b60206101a0510260e001516101805261014080516101805181818301106135885780820190509050815250815160010180835281141561294857505061014051612996576000815250612ba0565b610140516101805261012051600280820282158284830414171561358857905090506101a0526101c0600060ff818352015b610180516101e05261022060006002818352015b6020610220510260e00151610200526101e0516101805180820282158284830414171561358857905090506102005160028082028215828483041417156135885790509050808015613588578204905090506101e05281516001018083528114156129dc57505061018051610160526101a0516101405180820282158284830414171561358857905090506064808204905090506101e05160028082028215828483041417156135885790509050818183011061358857808201905090506101805180820282158284830414171561358857905090506101a0516064808210613588578082039050905061018051808202821582848304141715613588579050905060648082049050905060036101e0518082028215828483041417156135885790509050818183011061358857808201905090508080156135885782049050905061018052610160516101805111612b5e5760016101605161018051808210613588578082039050905011612b8957505061018051815250612ba056612b89565b60016101805161016051808210613588578082039050905011612b8957505061018051815250612ba0565b81516001018083528114156129c857505060006000fd5b565b6102405160e0526102605161010052612bbc6102a0612885565b6102a08051610300528060200151610320525061028051610340526103005160e05261032051610100526103405161012052612bf96102e0612935565b6102e051815250565b6102605161024051146135885760006102605112613588576002610260511215613588576000610240511261358857600261024051121561358857612c4861030061269e565b610300516102e0526102a05160e0526102c051610100526102e05161012052612c72610320612935565b61032051610300526102e05160028082028215828483041417156135885790509050610320526103005161034052606036610360376103c060006002818352015b610240516103c05118612ccd576102805161038052612cfe565b610260516103c0511415612ce457612d6256612cfe565b6102a06103c0516002811015613588576020020151610380525b6103608051610380518181830110613588578082019050905081525061034051610300518082028215828483041417156135885790509050610380516002808202821582848304141715613588579050905080801561358857820490509050610340525b8151600101808352811415612cb35750506103405161030051808202821582848304141715613588579050905060648082028215828483041417156135885790509050610320516002808202821582848304141715613588579050905080801561358857820490509050610340526103605161030051606480820282158284830414171561358857905090506103205180801561358857820490509050818183011061358857808201905090506103c052610300516103e052610400600060ff818352015b6103e0516103a0526103e0516103e0518082028215828483041417156135885790509050610340518181830110613588578082019050905060026103e05180820282158284830414171561358857905090506103c05181818301106135885780820190509050610300518082106135885780820390509050808015613588578204905090506103e0526103a0516103e05111612eec5760016103a0516103e051808210613588578082039050905011612f175750506103e051815250612f2e56612f17565b60016103e0516103a051808210613588578082039050905011612f175750506103e051815250612f2e565b8151600101808352811415612e2757505060006000fd5b565b600061010051126135885760026101005112156135885760e0516002808202821582848304141715613588579050905061018052610160516101a0526060366101c03761022060006002818352015b61010051610220511415612f965761301456612fb0565b6101206102205160028110156135885760200201516101e0525b6101c080516101e051818183011061358857808201905090508152506101a0516101605180820282158284830414171561358857905090506101e05160028082028215828483041417156135885790509050808015613588578204905090506101a0525b8151600101808352811415612f7f5750506101a051610160518082028215828483041417156135885790509050606480820282158284830414171561358857905090506101805160028082028215828483041417156135885790509050808015613588578204905090506101a0526101c0516101605160648082028215828483041417156135885790509050610180518080156135885782049050905081818301106135885780820190509050610220526101605161024052610260600060ff818352015b6102405161020052610240516102405180820282158284830414171561358857905090506101a0518181830110613588578082019050905060026102405180820282158284830414171561358857905090506102205181818301106135885780820190509050610160518082106135885780820390509050808015613588578204905090506102405261020051610240511161319e57600161020051610240518082106135885780820390509050116131c9575050610240518152506131e0566131c9565b600161024051610200518082106135885780820390509050116131c9575050610240518152506131e0565b81516001018083528114156130d957505060006000fd5b565b6131ed6102e061269e565b6102e0516102c0526132006103206127d9565b61032080516102e052806020015161030052506102e05160e05261030051610100526102c05161012052613235610340612935565b61034051610320526318160ddd610360526020610360600461037c6008545afa613264573d600060003e3d6000fd5b601f3d1115613588576103605161034052610320516102805161032051808202821582848304141715613588579050905061034051808015613588578204905090508082106135885780820390509050610360526102c05160e0526102a051610100526102e05161012052610300516101405261036051610160526132ea6103a0612f30565b6103a051610380526102e0516103a052610300516103c052600554600280820282158284830414171561358857905090506004808204905090506103e05261040060006002818352015b6000610420526102a05161040051186133a0576102e0610400516002811015613588576020020151610360518082028215828483041417156135885790509050610320518080156135885782049050905061038051808210613588578082039050905061042052613406565b6102e06104005160028110156135885760200201516102e061040051600281101561358857602002015161036051808202821582848304141715613588579050905061032051808015613588578204905090508082106135885780820390509050610420525b6103a0610400516002811015613588576020020180516103e0516104205180820282158284830414171561358857905090506402540be40080820490509050808210613588578082039050905081525081516001018083528114156133345750506103a06102a05160028110156135885760200201516102c05160e0526102a051610100526103a051610120526103c0516101405261036051610160526134ae610420612f30565b6104205180821061358857808203905090506104005260016104205264e8d4a510006104405261040051600180821061358857808203905090506104206102a051600281101561358857602002015180801561358857820490509050610400526102e06102a05160028110156135885760200201516103805180821061358857808203905090506104206102a0516002811015613588576020020151808015613588578204905090506104605261040051815261046051610400518082106135885780820390509050602082015261034051604082015250565b600080fd5b6101446136d1036101446000396101446136d1036000f35b600080fd000000000000000000000000ecb456ea5365865ebab8a2661b0c503410e9b347000000000000000000000000853d955acef822db058eb8505911ed77f175b99e000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000ecebb5b9ebc11025493f9339f53d1ffb11e2882500000000000000000000000000000000000000000000000000000000000005dc0000000000000000000000000000000000000000000000000000000017d78400000000000000000000000000000000000000000000000000000000012a05f200
60206136ee6080396080518060a01c6136e95760e05260206136ee016020816080396080518060a01c6136e957610100526020602082016080396080518060a01c6136e9576101205250602060606136ee016080396080518060a01c6136e9576101405261016060006002818352015b60006101006101605160028110156136e9576020020151146136e957815160010180835281141561006f5750506101005160015561012051600255602060806136ee0160803960805160648082028215828483041417156136e95790509050600955602060806136ee0160803960805160648082028215828483041417156136e95790509050600a55602060a06136ee01608039608051600555602060c06136ee0160803960805160065560e05160075542624f1a0081818301106136e95780820190509050601355610140516008556136d156600436101561000d57612698565b60046000601c37600051346135885763f446c1d0811861004a5761003261016061269e565b61016051606480820490509050610180526020610180f35b6376a2f0f0811861006f5761006061016061269e565b61016051610180526020610180f35b63bb7b8b80811861014a576100856102606127d9565b61026080516102e052806020015161030052506100a36102a061269e565b6102a051610320526102e05160e052610300516101005261032051610120526100cd6102c0612935565b6102c051610240526318160ddd610280526020610280600461029c6008545afa6100fc573d600060003e3d6000fd5b601f3d111561358857610280516102605261024051670de0b6b3a764000080820282158284830414171561358857905090506102605180801561358857820490509050610280526020610280f35b63ed8e84f38118610324576044358060011c613588576103605261016f6103a061269e565b6103a051610380526003546103a0526004546103c0526103a051610240526103c0516102605261038051610280526101a8610400612ba2565b610400516103e05261040060006002818352015b610360516101fb576103a06104005160028110156135885760200201805160206104005102600401358082106135885780820390509050815250610230565b6103a0610400516002811015613588576020020180516020610400510260040135818183011061358857808201905090508152505b81516001018083528114156101bc5750506103a051610240526103c051610260526103805161028052610264610420612ba2565b61042051610400526318160ddd610440526020610440600461045c6008545afa610293573d600060003e3d6000fd5b601f3d1115613588576104405161042052600061044052610360516102d1576103e051610400518082106135885780820390509050610440526102ec565b610400516103e0518082106135885780820390509050610440525b610440516104205180820282158284830414171561358857905090506103e05180801561358857820490509050610460526020610460f35b630b4c7e4d8118610983576000546135885760016000556012546135885761034d61038061269e565b6103805161036052600354610380526004546103a05261038051610240526103a0516102605261036051610280526103866103e0612ba2565b6103e0516103c0526008546103e0526318160ddd610420526020610420600461043c6103e0515afa6103bd573d600060003e3d6000fd5b601f3d111561358857610420516104005261038051610420526103a0516104405261046060006002818352015b6104005161040657600060206104605102600401351115613588575b6104206104605160028110156135885760200201805160206104605102600401358181830110613588578082019050905081525081516001018083528114156103ea57505061042051610240526104405161026052610360516102805261046e610480612ba2565b61048051610460526103c0516104605111156135885761046051610480526060366104a037600061040051116104b9576104205160035561044051600455610460516104e0526106f4565b60055460028082028215828483041417156135885790509050600480820490509050610500526006546105205261054060006002818352015b6104605161038061054051600281101561358857602002015180820282158284830414171561358857905090506103c05180801561358857820490509050610560526000610580526104206105405160028110156135885760200201516105a0526105a051610560511161057f576105a0516105605180821061358857808203905090506105805261059a565b610560516105a0518082106135885780820390509050610580525b610500516105805180820282158284830414171561358857905090506402540be400808204905090506104a06105405160028110156135885760200201526105a0516104a06105405160028110156135885760200201516105205180820282158284830414171561358857905090506402540be4008082049050905080821061358857808203905090506001610540516002811015613588570260030155610420610540516002811015613588576020020180516104a0610540516002811015613588576020020151808210613588578082039050905081525081516001018083528114156104f25750506104205161024052610440516102605261036051610280526106a8610540612ba2565b610540516104805261040051610480516103c051808210613588578082039050905080820282158284830414171561358857905090506103c051808015613588578204905090506104e0525b6044356104e0511015610778576014610500527f536c697070616765207363726577656420796f750000000000000000000000006105205261050050610500518061052001818260206001820306601f82010390500336823750506308c379a06104c05260206104e0526105005160206001820306601f82010390506044016104dcfd5b61050060006002818352015b6000602061050051026004013511156108b05760006004610560527f23b872dd00000000000000000000000000000000000000000000000000000000610580526105606004806020846105a00101826020850160045afa505080518201915050336020826105a0010152602081019050306020826105a001015260208101905060206105005102600401356020826105a0010152602081019050806105a0526105a0505060206106606105a0516105c0600060016105005160028110156135885702600101545af161085b573d600060003e3d6000fd5b61064060203d80821161086e5781610870565b805b905090508152805160200180610520828460045afa9050505060006105205111156108b057610540516105205181816020036008021c9050905015613588575b81516001018083528114156107845750506340c10f196105005233610520526104e051610540526020610500604461051c60006103e0515af16108f8573d600060003e3d6000fd5b601f3d11156135885761050050337f26f55a85081d24974e85c6c00045d0f0453991e95873f52bff0d21af4079a76860043561050052602435610520526104a051610540526104c051610560526104605161058052610400516104e051818183011061358857808201905090506105a05260c0610500a26104e0516105005260206105006000600055f35b635e0d443f8118610b5a576004358060801d81607f1d1861358857610420526024358060801d81607f1d1861358857610440526109c16104a06127d9565b6104a080516104605280602001516104805250670de0b6b3a76400006104a0526c0c9f2c9cd04674edea400000006104c0526104606104205160028110156135885760200201516044356104a06104205160028110156135885760200201518082028215828483041417156135885790509050670de0b6b3a764000080820490509050818183011061358857808201905090506104e052610420516102405261044051610260526104e05161028052610460516102a052610480516102c052610a8b610520612c02565b610520516105005261046061044051600281101561358857602002015161050051808210613588578082039050905060018082106135885780820390509050610520526005546105205180820282158284830414171561358857905090506402540be400808204905090506105405261052051610540518082106135885780820390509050670de0b6b3a764000080820282158284830414171561358857905090506104a061044051600281101561358857602002015180801561358857820490509050610560526020610560f35b633df02124811861116d576004358060801d81607f1d1861358857610420526024358060801d81607f1d1861358857610440526000546135885760016000556012546135885760035461046052600454610480526104605160e0526104805161010052610bc86104e0612885565b6104e080516104a05280602001516104c05250670de0b6b3a76400006104e0526c0c9f2c9cd04674edea40000000610500526104a06104205160028110156135885760200201516044356104e06104205160028110156135885760200201518082028215828483041417156135885790509050670de0b6b3a76400008082049050905081818301106135885780820190509050610520526104205161024052610440516102605261052051610280526104a0516102a0526104c0516102c052610c92610560612c02565b61056051610540526104a061044051600281101561358857602002015161054051808210613588578082039050905060018082106135885780820390509050610560526105605160055480820282158284830414171561358857905090506402540be400808204905090506105805261056051610580518082106135885780820390509050670de0b6b3a764000080820282158284830414171561358857905090506104e06104405160028110156135885760200201518080156135885782049050905061056052606435610560511015610e0357602e6105a0527f45786368616e676520726573756c74656420696e20666577657220636f696e736105c0527f207468616e2065787065637465640000000000000000000000000000000000006105e0526105a0506105a051806105c001818260206001820306601f82010390500336823750506308c379a0610560526020610580526105a05160206001820306601f820103905060440161057cfd5b6105805160065480820282158284830414171561358857905090506402540be400808204905090506105a0526105a051670de0b6b3a764000080820282158284830414171561358857905090506104e0610440516002811015613588576020020151808015613588578204905090506105a0526104606104205160028110156135885760200201516044358181830110613588578082019050905060016104205160028110156135885702600301556104606104405160028110156135885760200201516105605180821061358857808203905090506105a0518082106135885780820390509050600161044051600281101561358857026003015560006004610600527f23b872dd00000000000000000000000000000000000000000000000000000000610620526106006004806020846106400101826020850160045afa505080518201915050336020826106400101526020810190503060208261064001015260208101905060443560208261064001015260208101905080610640526106405050602061070061064051610660600060016104205160028110156135885702600101545af1610fbb573d600060003e3d6000fd5b6106e060203d808211610fce5781610fd0565b805b9050905081528051602001806105c0828460045afa9050505060006105c0511115611010576105e0516105c05181816020036008021c9050905015613588575b60006004610600527fa9059cbb00000000000000000000000000000000000000000000000000000000610620526106006004806020846106400101826020850160045afa50508051820191505033602082610640010152602081019050610560516020826106400101526020810190508061064052610640505060206106e061064051610660600060016104405160028110156135885702600101545af16110bd573d600060003e3d6000fd5b6106c060203d8082116110d057816110d2565b805b9050905081528051602001806105c0828460045afa9050505060006105c0511115611112576105e0516105c05181816020036008021c9050905015613588575b337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd97140610420516106005260443561062052610440516106405261056051610660526080610600a2610560516106005260206106006000600055f35b635b36389c81186114da5760005461358857600160005560085460e0526318160ddd610120526020610120600461013c60e0515afa6111b1573d600060003e3d6000fd5b601f3d11156135885761012051610100526040366101203761016060006002818352015b60016101605160028110156135885702600301546101805261018051600435808202821582848304141715613588579050905061010051808015613588578204905090506101a05260206101605102602401356101a05110156112ce5760306101c0527f5769746864726177616c20726573756c74656420696e20666577657220636f696101e0527f6e73207468616e20657870656374656400000000000000000000000000000000610200526101c0506101c051806101e001818260206001820306601f82010390500336823750506308c379a06101805260206101a0526101c05160206001820306601f820103905060440161019cfd5b610180516101a051808210613588578082039050905060016101605160028110156135885702600301556101a05161012061016051600281101561358857602002015260006004610200527fa9059cbb00000000000000000000000000000000000000000000000000000000610220526102006004806020846102400101826020850160045afa505080518201915050336020826102400101526020810190506101a0516020826102400101526020810190508061024052610240505060206102e061024051610260600060016101605160028110156135885702600101545af16113be573d600060003e3d6000fd5b6102c060203d8082116113d157816113d3565b805b9050905081528051602001806101c0828460045afa9050505060006101c0511115611413576101e0516101c05181816020036008021c9050905015613588575b81516001018083528114156111d55750506379cc67906101605233610180526004356101a0526020610160604461017c600060e0515af1611459573d600060003e3d6000fd5b601f3d11156135885761016050337f7c363854ccf79623411f8995b362bce5eddff18c927edc6f5dbbb5e05819a82c610120516101605261014051610180526040366101a0376101005160043580821061358857808203905090506101e05260a0610160a26101205161016052610140516101805260406101606000600055f35b63e31032738118611af0576000546135885760016000556012546135885761150361038061269e565b6103805161036052600354610380526004546103a05261038051610240526103a05161026052610360516102805261153c6103e0612ba2565b6103e0516103c052610380516103e0526103a0516104005261042060006002818352015b6103e0610420516002811015613588576020020180516020610420510260040135808210613588578082039050905081525081516001018083528114156115605750506103e05161024052610400516102605261036051610280526115c6610440612ba2565b6104405161042052600554600280820282158284830414171561358857905090506004808204905090506104405260065461046052604036610480376104c060006002818352015b6103e06104c05160028110156135885760200201516104e052610420516103806104c051600281101561358857602002015180820282158284830414171561358857905090506103c05180801561358857820490509050610500526000610520526104e051610500511161169b576104e051610500518082106135885780820390509050610520526116b6565b610500516104e0518082106135885780820390509050610520525b610440516105205180820282158284830414171561358857905090506402540be400808204905090506104806104c05160028110156135885760200201526104e0516104806104c05160028110156135885760200201516104605180820282158284830414171561358857905090506402540be40080820490509050808210613588578082039050905060016104c05160028110156135885702600301556104e0516104806104c051600281101561358857602002015180821061358857808203905090506103e06104c0516002811015613588576020020152815160010180835281141561160e5750506103e05161024052610400516102605261036051610280526117c46104e0612ba2565b6104e0516104c0526008546104e0526318160ddd610520526020610520600461053c6104e0515afa6117fb573d600060003e3d6000fd5b601f3d11156135885761052051610500526103c0516104c05180821061358857808203905090506105005180820282158284830414171561358857905090506103c0518080156135885782049050905061052052600061052051146135885761052080516001818183011061358857808201905090508152506044356105205111156118f8576014610540527f536c697070616765207363726577656420796f750000000000000000000000006105605261054050610540518061056001818260206001820306601f82010390500336823750506308c379a0610500526020610520526105405160206001820306601f820103905060440161051cfd5b6379cc679061054052336105605261052051610580526020610540604461055c60006104e0515af161192f573d600060003e3d6000fd5b601f3d1115613588576105405061054060006002818352015b6000602061054051026004013514611a6357600060046105a0527fa9059cbb000000000000000000000000000000000000000000000000000000006105c0526105a06004806020846105e00101826020850160045afa505080518201915050336020826105e001015260208101905060206105405102600401356020826105e0010152602081019050806105e0526105e0505060206106806105e051610600600060016105405160028110156135885702600101545af1611a0e573d600060003e3d6000fd5b61066060203d808211611a215781611a23565b805b905090508152805160200180610560828460045afa905050506000610560511115611a6357610580516105605181816020036008021c9050905015613588575b8151600101808352811415611948575050337f2b5508378d7e19e0d5fa338419034731416c4f5b219a10379956f764317fd47e600435610540526024356105605261048051610580526104a0516105a052610420516105c052610500516105205180821061358857808203905090506105e05260c0610540a2610520516105405260206105406000600055f35b63cc2b27d78118611b38576024358060801d81607f1d18613588576104805260043561028052610480516102a052611b296104a06131e2565b6104a051610500526020610500f35b631a4d01d28118611e35576024358060801d81607f1d186135885761048052600054613588576001600055601254613588576060366104a03760043561028052610480516102a052611b8b6105006131e2565b61050080516104a05260208101516104c05260408101516104e052506044356104a0511015611c2b576018610500527f4e6f7420656e6f75676820636f696e732072656d6f76656400000000000000006105205261050050610500518061052001818260206001820306601f82010390500336823750506308c379a06104c05260206104e0526105005160206001820306601f82010390506044016104dcfd5b6001610480516002811015613588570260030180546104a0516104c05160065480820282158284830414171561358857905090506402540be400808204905090508181830110613588578082019050905080821061358857808203905090508155506379cc6790610500523361052052600435610540526020610500604461051c60006008545af1611cc2573d600060003e3d6000fd5b601f3d1115613588576105005060006004610540527fa9059cbb00000000000000000000000000000000000000000000000000000000610560526105406004806020846105800101826020850160045afa505080518201915050336020826105800101526020810190506104a051602082610580010152602081019050806105805261058050506020610620610580516105a0600060016104805160028110156135885702600101545af1611d7c573d600060003e3d6000fd5b61060060203d808211611d8f5781611d91565b805b905090508152805160200180610500828460045afa905050506000610500511115611dd157610520516105005181816020036008021c9050905015613588575b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a0600435610540526104a051610560526104e0516004358082106135885780820390509050610580526060610540a26104a0516105405260206105406000600055f35b633c157e648118611f8857600754331861358857600b5462015180818183011061358857808201905090504210613588574262015180818183011061358857808201905090506024351061358857611e8e61018061269e565b61018051610160526004356064808202821582848304141715613588579050905061018052600060043511611ec4576000611ecd565b620f4240600435105b1561358857610160516101805110611f075761016051600a8082028215828483041417156135885790509050610180511161358857611f2b565b6101605161018051600a808202821582848304141715613588579050905010613588575b6101605160095561018051600a5542600b55602435600c557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c254610160516101a052610180516101c052426101e0526024356102005260806101a0a1005b63551a65888118611ffb57600754331861358857611fa761018061269e565b61018051610160526101605160095561016051600a5542600b5542600c557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc2019386101605161018052426101a0526040610180a1005b635b5a1467811861209657600754331861358857600d546135885764012a05f20060043511613588576402540be4006024351161358857426203f4808181830110613588578082019050905060e05260e051600d55600435600f5560243560105560e0517f351fc5da2fbf480f2225debf3664a4bc90fa9923743aad58b4603f648e931fe060043561010052602435610120526040610100a2005b634f12fe97811861211457600754331861358857600d544210613588576000600d5414613588576000600d55600f5460e0526010546101005260e051600555610100516006557fbe12859b636aed607d5230b2cc2711f68d70e51060e6cca1f575ef5d2fcc95d160e0516101205261010051610140526040610120a1005b63226840fb811861212f576007543318613588576000600d55005b636b441a4081186121ae576004358060a01c6135885760e052600754331861358857600e5461358857426203f480818183011061358857808201905090506101005261010051600e5560e05160115560e051610100517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb9356000610120a3005b636a1c05ae811861221257600754331861358857600e544210613588576000600e5414613588576000600e5560115460e05260e05160075560e0517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c6000610100a2005b6386fbf193811861222d576007543318613588576000600e55005b63e2e7d26481186122a9576370a0823160e0523061010052602060e0602460fc600160043560028110156135885702600101545afa612271573d600060003e3d6000fd5b601f3d11156135885760e051600160043560028110156135885702600301548082106135885780820390509050610120526020610120f35b6330c54085811861244f5760075433186135885760e060006002818352015b600160e0516002811015613588570260010154610100526370a082316101405230610160526020610140602461015c610100515afa61230c573d600060003e3d6000fd5b601f3d11156135885761014051600160e0516002811015613588570260030154808210613588578082039050905061012052600061012051111561243c5760006004610180527fa9059cbb000000000000000000000000000000000000000000000000000000006101a0526101806004806020846101c00101826020850160045afa505080518201915050336020826101c0010152602081019050610120516020826101c0010152602081019050806101c0526101c0505060206102606101c0516101e06000610100515af16123e7573d600060003e3d6000fd5b61024060203d8082116123fa57816123fc565b805b905090508152805160200180610140828460045afa90505050600061014051111561243c57610160516101405181816020036008021c9050905015613588575b81516001018083528114156122c8575050005b63524c390181186124dd5760075433186135885760e060006002818352015b6370a082316101005230610120526020610100602461011c600160e05160028110156135885702600101545afa6124aa573d600060003e3d6000fd5b601f3d11156135885761010051600160e0516002811015613588570260030155815160010180835281141561246e575050005b63e3698853811861250257600754331861358857426013541115613588576001601255005b633046f972811861251d576007543318613588576000601255005b63c66106578118612544576001600435600281101561358857026001015460e052602060e0f35b634903b0d1811861256b576001600435600281101561358857026003015460e052602060e0f35b63ddca3f4381186125825760055460e052602060e0f35b63fee3f7f981186125995760065460e052602060e0f35b638da5cb5b81186125b05760075460e052602060e0f35b6382c6306681186125c75760085460e052602060e0f35b635409491a81186125de5760095460e052602060e0f35b63b4b577ad81186125f557600a5460e052602060e0f35b632081066c811861260c57600b5460e052602060e0f35b6314052288811861262357600c5460e052602060e0f35b63405e28f8811861263a57600d5460e052602060e0f35b63e0a0b586811861265157600e5460e052602060e0f35b6358680d0b811861266857600f5460e052602060e0f35b63e3824462811861267f5760105460e052602060e0f35b631ec0cdc181186126965760115460e052602060e0f35b505b60006000fd5b600c5460e052600a546101005260e05142106126c457610100518152506127d7566127d7565b60095461012052600b546101405261012051610100511161275c57610120516101205161010051808210613588578082039050905042610140518082106135885780820390509050808202821582848304141715613588579050905060e0516101405180821061358857808203905090508080156135885782049050905080821061358857808203905090508152506127d7566127d7565b610120516101005161012051808210613588578082039050905042610140518082106135885780820390509050808202821582848304141715613588579050905060e05161014051808210613588578082039050905080801561358857820490509050818183011061358857808201905090508152506127d7565b565b670de0b6b3a764000060e0526c0c9f2c9cd04674edea400000006101005261012060006002818352015b60e061012051600281101561358857602002015160016101205160028110156135885702600301548082028215828483041417156135885790509050670de0b6b3a76400008082049050905060e0610120516002811015613588576020020152815160010180835281141561280357505060e051815261010051816020015250565b670de0b6b3a7640000610120526c0c9f2c9cd04674edea400000006101405261016060006002818352015b61012061016051600281101561358857602002015160e06101605160028110156135885760200201518082028215828483041417156135885790509050670de0b6b3a76400008082049050905061012061016051600281101561358857602002015281516001018083528114156128b057505061012051815261014051816020015250565b604036610140376101a060006002818352015b60206101a0510260e001516101805261014080516101805181818301106135885780820190509050815250815160010180835281141561294857505061014051612996576000815250612ba0565b610140516101805261012051600280820282158284830414171561358857905090506101a0526101c0600060ff818352015b610180516101e05261022060006002818352015b6020610220510260e00151610200526101e0516101805180820282158284830414171561358857905090506102005160028082028215828483041417156135885790509050808015613588578204905090506101e05281516001018083528114156129dc57505061018051610160526101a0516101405180820282158284830414171561358857905090506064808204905090506101e05160028082028215828483041417156135885790509050818183011061358857808201905090506101805180820282158284830414171561358857905090506101a0516064808210613588578082039050905061018051808202821582848304141715613588579050905060648082049050905060036101e0518082028215828483041417156135885790509050818183011061358857808201905090508080156135885782049050905061018052610160516101805111612b5e5760016101605161018051808210613588578082039050905011612b8957505061018051815250612ba056612b89565b60016101805161016051808210613588578082039050905011612b8957505061018051815250612ba0565b81516001018083528114156129c857505060006000fd5b565b6102405160e0526102605161010052612bbc6102a0612885565b6102a08051610300528060200151610320525061028051610340526103005160e05261032051610100526103405161012052612bf96102e0612935565b6102e051815250565b6102605161024051146135885760006102605112613588576002610260511215613588576000610240511261358857600261024051121561358857612c4861030061269e565b610300516102e0526102a05160e0526102c051610100526102e05161012052612c72610320612935565b61032051610300526102e05160028082028215828483041417156135885790509050610320526103005161034052606036610360376103c060006002818352015b610240516103c05118612ccd576102805161038052612cfe565b610260516103c0511415612ce457612d6256612cfe565b6102a06103c0516002811015613588576020020151610380525b6103608051610380518181830110613588578082019050905081525061034051610300518082028215828483041417156135885790509050610380516002808202821582848304141715613588579050905080801561358857820490509050610340525b8151600101808352811415612cb35750506103405161030051808202821582848304141715613588579050905060648082028215828483041417156135885790509050610320516002808202821582848304141715613588579050905080801561358857820490509050610340526103605161030051606480820282158284830414171561358857905090506103205180801561358857820490509050818183011061358857808201905090506103c052610300516103e052610400600060ff818352015b6103e0516103a0526103e0516103e0518082028215828483041417156135885790509050610340518181830110613588578082019050905060026103e05180820282158284830414171561358857905090506103c05181818301106135885780820190509050610300518082106135885780820390509050808015613588578204905090506103e0526103a0516103e05111612eec5760016103a0516103e051808210613588578082039050905011612f175750506103e051815250612f2e56612f17565b60016103e0516103a051808210613588578082039050905011612f175750506103e051815250612f2e565b8151600101808352811415612e2757505060006000fd5b565b600061010051126135885760026101005112156135885760e0516002808202821582848304141715613588579050905061018052610160516101a0526060366101c03761022060006002818352015b61010051610220511415612f965761301456612fb0565b6101206102205160028110156135885760200201516101e0525b6101c080516101e051818183011061358857808201905090508152506101a0516101605180820282158284830414171561358857905090506101e05160028082028215828483041417156135885790509050808015613588578204905090506101a0525b8151600101808352811415612f7f5750506101a051610160518082028215828483041417156135885790509050606480820282158284830414171561358857905090506101805160028082028215828483041417156135885790509050808015613588578204905090506101a0526101c0516101605160648082028215828483041417156135885790509050610180518080156135885782049050905081818301106135885780820190509050610220526101605161024052610260600060ff818352015b6102405161020052610240516102405180820282158284830414171561358857905090506101a0518181830110613588578082019050905060026102405180820282158284830414171561358857905090506102205181818301106135885780820190509050610160518082106135885780820390509050808015613588578204905090506102405261020051610240511161319e57600161020051610240518082106135885780820390509050116131c9575050610240518152506131e0566131c9565b600161024051610200518082106135885780820390509050116131c9575050610240518152506131e0565b81516001018083528114156130d957505060006000fd5b565b6131ed6102e061269e565b6102e0516102c0526132006103206127d9565b61032080516102e052806020015161030052506102e05160e05261030051610100526102c05161012052613235610340612935565b61034051610320526318160ddd610360526020610360600461037c6008545afa613264573d600060003e3d6000fd5b601f3d1115613588576103605161034052610320516102805161032051808202821582848304141715613588579050905061034051808015613588578204905090508082106135885780820390509050610360526102c05160e0526102a051610100526102e05161012052610300516101405261036051610160526132ea6103a0612f30565b6103a051610380526102e0516103a052610300516103c052600554600280820282158284830414171561358857905090506004808204905090506103e05261040060006002818352015b6000610420526102a05161040051186133a0576102e0610400516002811015613588576020020151610360518082028215828483041417156135885790509050610320518080156135885782049050905061038051808210613588578082039050905061042052613406565b6102e06104005160028110156135885760200201516102e061040051600281101561358857602002015161036051808202821582848304141715613588579050905061032051808015613588578204905090508082106135885780820390509050610420525b6103a0610400516002811015613588576020020180516103e0516104205180820282158284830414171561358857905090506402540be40080820490509050808210613588578082039050905081525081516001018083528114156133345750506103a06102a05160028110156135885760200201516102c05160e0526102a051610100526103a051610120526103c0516101405261036051610160526134ae610420612f30565b6104205180821061358857808203905090506104005260016104205264e8d4a510006104405261040051600180821061358857808203905090506104206102a051600281101561358857602002015180801561358857820490509050610400526102e06102a05160028110156135885760200201516103805180821061358857808203905090506104206102a0516002811015613588576020020151808015613588578204905090506104605261040051815261046051610400518082106135885780820390509050602082015261034051604082015250565b600080fd5b6101446136d1036101446000396101446136d1036000f35b600080fd000000000000000000000000ecb456ea5365865ebab8a2661b0c503410e9b347000000000000000000000000853d955acef822db058eb8505911ed77f175b99e000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000ecebb5b9ebc11025493f9339f53d1ffb11e2882500000000000000000000000000000000000000000000000000000000000005dc0000000000000000000000000000000000000000000000000000000017d78400000000000000000000000000000000000000000000000000000000012a05f200