Vyper_contract
Deploy on AlchemyContract Information
The following smart contract returns the value of the variable `max_price`. It is assumed that `max_price` has been previously defined and assigned a value. This code is written in Solidity programming language.
More Info
# @version 0.3.1
# (c) Curve.Fi, 2021
# Pool for two crypto assets
# Expected coins:
# eth/whatever
interface CurveToken:
def totalSupply() -> uint256: view
def mint(_to: address, _value: uint256) -> bool: nonpayable
def mint_relative(_to: address, frac: uint256) -> uint256: nonpayable
def burnFrom(_to: address, _value: uint256) -> bool: nonpayable
interface ERC20:
def transfer(_to: address, _value: uint256) -> bool: nonpayable
def transferFrom(_from: address, _to: address, _value: uint256) -> bool: nonpayable
def decimals() -> uint256: view
def balanceOf(_user: address) -> uint256: view
interface WETH:
def deposit(): payable
def withdraw(_amount: uint256): nonpayable
# Events
event TokenExchange:
buyer: indexed(address)
sold_id: uint256
tokens_sold: uint256
bought_id: uint256
tokens_bought: uint256
event AddLiquidity:
provider: indexed(address)
token_amounts: uint256[N_COINS]
fee: uint256
token_supply: uint256
event RemoveLiquidity:
provider: indexed(address)
token_amounts: uint256[N_COINS]
token_supply: uint256
event RemoveLiquidityOne:
provider: indexed(address)
token_amount: uint256
coin_index: uint256
coin_amount: uint256
event CommitNewAdmin:
deadline: indexed(uint256)
admin: indexed(address)
event NewAdmin:
admin: indexed(address)
event CommitNewParameters:
deadline: indexed(uint256)
admin_fee: uint256
mid_fee: uint256
out_fee: uint256
fee_gamma: uint256
allowed_extra_profit: uint256
adjustment_step: uint256
ma_half_time: uint256
event NewParameters:
admin_fee: uint256
mid_fee: uint256
out_fee: uint256
fee_gamma: uint256
allowed_extra_profit: uint256
adjustment_step: uint256
ma_half_time: uint256
event RampAgamma:
initial_A: uint256
future_A: uint256
initial_gamma: uint256
future_gamma: uint256
initial_time: uint256
future_time: uint256
event StopRampA:
current_A: uint256
current_gamma: uint256
time: uint256
event ClaimAdminFee:
admin: indexed(address)
tokens: uint256
N_COINS: constant(int128) = 2
PRECISION: constant(uint256) = 10 ** 18 # The precision to convert to
A_MULTIPLIER: constant(uint256) = 10000
token: immutable(address)
coins: immutable(address[N_COINS])
price_scale: public(uint256) # Internal price scale
price_oracle: public(uint256) # Price target given by MA
last_prices: public(uint256)
last_prices_timestamp: public(uint256)
initial_A_gamma: public(uint256)
future_A_gamma: public(uint256)
initial_A_gamma_time: public(uint256)
future_A_gamma_time: public(uint256)
allowed_extra_profit: public(uint256) # 2 * 10**12 - recommended value
future_allowed_extra_profit: public(uint256)
fee_gamma: public(uint256)
future_fee_gamma: public(uint256)
adjustment_step: public(uint256)
future_adjustment_step: public(uint256)
ma_half_time: public(uint256)
future_ma_half_time: public(uint256)
mid_fee: public(uint256)
out_fee: public(uint256)
admin_fee: public(uint256)
future_mid_fee: public(uint256)
future_out_fee: public(uint256)
future_admin_fee: public(uint256)
balances: public(uint256[N_COINS])
D: public(uint256)
owner: public(address)
future_owner: public(address)
xcp_profit: public(uint256)
xcp_profit_a: public(uint256) # Full profit at last claim of admin fees
virtual_price: public(uint256) # Cached (fast to read) virtual price also used internally
not_adjusted: bool
is_killed: public(bool)
kill_deadline: public(uint256)
transfer_ownership_deadline: public(uint256)
admin_actions_deadline: public(uint256)
admin_fee_receiver: public(address)
KILL_DEADLINE_DT: constant(uint256) = 2 * 30 * 86400
ADMIN_ACTIONS_DELAY: constant(uint256) = 3 * 86400
MIN_RAMP_TIME: constant(uint256) = 86400
MAX_ADMIN_FEE: constant(uint256) = 10 * 10 ** 9
MIN_FEE: constant(uint256) = 5 * 10 ** 5 # 0.5 bps
MAX_FEE: constant(uint256) = 10 * 10 ** 9
MAX_A_CHANGE: constant(uint256) = 10
NOISE_FEE: constant(uint256) = 10**5 # 0.1 bps
MIN_GAMMA: constant(uint256) = 10**10
MAX_GAMMA: constant(uint256) = 2 * 10**16
MIN_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER / 10
MAX_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER * 100000
# This must be changed for different N_COINS
# For example:
# N_COINS = 3 -> 1 (10**18 -> 10**18)
# N_COINS = 4 -> 10**8 (10**18 -> 10**10)
# PRICE_PRECISION_MUL: constant(uint256) = 1
PRECISIONS: immutable(uint256[N_COINS])
EXP_PRECISION: constant(uint256) = 10**10
ETH_INDEX: constant(uint256) = 0 # Can put it to something big to turn the logic off
@external
def __init__(
owner: address,
admin_fee_receiver: address,
A: uint256,
gamma: uint256,
mid_fee: uint256,
out_fee: uint256,
allowed_extra_profit: uint256,
fee_gamma: uint256,
adjustment_step: uint256,
admin_fee: uint256,
ma_half_time: uint256,
initial_price: uint256,
_token: address,
_coins: address[N_COINS]
):
self.owner = owner
# Pack A and gamma:
# shifted A + gamma
A_gamma: uint256 = shift(A, 128)
A_gamma = bitwise_or(A_gamma, gamma)
self.initial_A_gamma = A_gamma
self.future_A_gamma = A_gamma
self.mid_fee = mid_fee
self.out_fee = out_fee
self.allowed_extra_profit = allowed_extra_profit
self.fee_gamma = fee_gamma
self.adjustment_step = adjustment_step
self.admin_fee = admin_fee
self.price_scale = initial_price
self.price_oracle = initial_price
self.last_prices = initial_price
self.last_prices_timestamp = block.timestamp
self.ma_half_time = ma_half_time
self.xcp_profit_a = 10**18
self.kill_deadline = block.timestamp + KILL_DEADLINE_DT
self.admin_fee_receiver = admin_fee_receiver
token = _token
coins = _coins
PRECISIONS = [10 ** (18 - ERC20(_coins[0]).decimals()),
10 ** (18 - ERC20(_coins[1]).decimals())]
@payable
@external
def __default__():
pass
### Math functions
@internal
@pure
def geometric_mean(unsorted_x: uint256[N_COINS], sort: bool) -> uint256:
"""
(x[0] * x[1] * ...) ** (1/N)
"""
x: uint256[N_COINS] = unsorted_x
if sort and x[0] < x[1]:
x = [unsorted_x[1], unsorted_x[0]]
D: uint256 = x[0]
diff: uint256 = 0
for i in range(255):
D_prev: uint256 = D
# tmp: uint256 = 10**18
# for _x in x:
# tmp = tmp * _x / D
# D = D * ((N_COINS - 1) * 10**18 + tmp) / (N_COINS * 10**18)
# line below makes it for 2 coins
D = (D + x[0] * x[1] / D) / N_COINS
if D > D_prev:
diff = D - D_prev
else:
diff = D_prev - D
if diff <= 1 or diff * 10**18 < D:
return D
raise "Did not converge"
@internal
@view
def newton_D(ANN: uint256, gamma: uint256, x_unsorted: uint256[N_COINS]) -> uint256:
"""
Finding the invariant using Newton method.
ANN is higher by the factor A_MULTIPLIER
ANN is already A * N**N
Currently uses 60k gas
"""
# Safety checks
assert ANN > MIN_A - 1 and ANN < MAX_A + 1 # dev: unsafe values A
assert gamma > MIN_GAMMA - 1 and gamma < MAX_GAMMA + 1 # dev: unsafe values gamma
# Initial value of invariant D is that for constant-product invariant
x: uint256[N_COINS] = x_unsorted
if x[0] < x[1]:
x = [x_unsorted[1], x_unsorted[0]]
assert x[0] > 10**9 - 1 and x[0] < 10**15 * 10**18 + 1 # dev: unsafe values x[0]
assert x[1] * 10**18 / x[0] > 10**14-1 # dev: unsafe values x[i] (input)
D: uint256 = N_COINS * self.geometric_mean(x, False)
S: uint256 = x[0] + x[1]
for i in range(255):
D_prev: uint256 = D
# K0: uint256 = 10**18
# for _x in x:
# K0 = K0 * _x * N_COINS / D
# collapsed for 2 coins
K0: uint256 = (10**18 * N_COINS**2) * x[0] / D * x[1] / D
_g1k0: uint256 = gamma + 10**18
if _g1k0 > K0:
_g1k0 = _g1k0 - K0 + 1
else:
_g1k0 = K0 - _g1k0 + 1
# D / (A * N**N) * _g1k0**2 / gamma**2
mul1: uint256 = 10**18 * D / gamma * _g1k0 / gamma * _g1k0 * A_MULTIPLIER / ANN
# 2*N*K0 / _g1k0
mul2: uint256 = (2 * 10**18) * N_COINS * K0 / _g1k0
neg_fprime: uint256 = (S + S * mul2 / 10**18) + mul1 * N_COINS / K0 - mul2 * D / 10**18
# D -= f / fprime
D_plus: uint256 = D * (neg_fprime + S) / neg_fprime
D_minus: uint256 = D*D / neg_fprime
if 10**18 > K0:
D_minus += D * (mul1 / neg_fprime) / 10**18 * (10**18 - K0) / K0
else:
D_minus -= D * (mul1 / neg_fprime) / 10**18 * (K0 - 10**18) / K0
if D_plus > D_minus:
D = D_plus - D_minus
else:
D = (D_minus - D_plus) / 2
diff: uint256 = 0
if D > D_prev:
diff = D - D_prev
else:
diff = D_prev - D
if diff * 10**14 < max(10**16, D): # Could reduce precision for gas efficiency here
# Test that we are safe with the next newton_y
for _x in x:
frac: uint256 = _x * 10**18 / D
assert (frac > 10**16 - 1) and (frac < 10**20 + 1) # dev: unsafe values x[i]
return D
raise "Did not converge"
@internal
@pure
def newton_y(ANN: uint256, gamma: uint256, x: uint256[N_COINS], D: uint256, i: uint256) -> uint256:
"""
Calculating x[i] given other balances x[0..N_COINS-1] and invariant D
ANN = A * N**N
"""
# Safety checks
assert ANN > MIN_A - 1 and ANN < MAX_A + 1 # dev: unsafe values A
assert gamma > MIN_GAMMA - 1 and gamma < MAX_GAMMA + 1 # dev: unsafe values gamma
assert D > 10**17 - 1 and D < 10**15 * 10**18 + 1 # dev: unsafe values D
x_j: uint256 = x[1 - i]
y: uint256 = D**2 / (x_j * N_COINS**2)
K0_i: uint256 = (10**18 * N_COINS) * x_j / D
# S_i = x_j
# frac = x_j * 1e18 / D => frac = K0_i / N_COINS
assert (K0_i > 10**16*N_COINS - 1) and (K0_i < 10**20*N_COINS + 1) # dev: unsafe values x[i]
# x_sorted: uint256[N_COINS] = x
# x_sorted[i] = 0
# x_sorted = self.sort(x_sorted) # From high to low
# x[not i] instead of x_sorted since x_soted has only 1 element
convergence_limit: uint256 = max(max(x_j / 10**14, D / 10**14), 100)
for j in range(255):
y_prev: uint256 = y
K0: uint256 = K0_i * y * N_COINS / D
S: uint256 = x_j + y
_g1k0: uint256 = gamma + 10**18
if _g1k0 > K0:
_g1k0 = _g1k0 - K0 + 1
else:
_g1k0 = K0 - _g1k0 + 1
# D / (A * N**N) * _g1k0**2 / gamma**2
mul1: uint256 = 10**18 * D / gamma * _g1k0 / gamma * _g1k0 * A_MULTIPLIER / ANN
# 2*K0 / _g1k0
mul2: uint256 = 10**18 + (2 * 10**18) * K0 / _g1k0
yfprime: uint256 = 10**18 * y + S * mul2 + mul1
_dyfprime: uint256 = D * mul2
if yfprime < _dyfprime:
y = y_prev / 2
continue
else:
yfprime -= _dyfprime
fprime: uint256 = yfprime / y
# y -= f / f_prime; y = (y * fprime - f) / fprime
# y = (yfprime + 10**18 * D - 10**18 * S) // fprime + mul1 // fprime * (10**18 - K0) // K0
y_minus: uint256 = mul1 / fprime
y_plus: uint256 = (yfprime + 10**18 * D) / fprime + y_minus * 10**18 / K0
y_minus += 10**18 * S / fprime
if y_plus < y_minus:
y = y_prev / 2
else:
y = y_plus - y_minus
diff: uint256 = 0
if y > y_prev:
diff = y - y_prev
else:
diff = y_prev - y
if diff < max(convergence_limit, y / 10**14):
frac: uint256 = y * 10**18 / D
assert (frac > 10**16 - 1) and (frac < 10**20 + 1) # dev: unsafe value for y
return y
raise "Did not converge"
@internal
@pure
def halfpow(power: uint256) -> uint256:
"""
1e18 * 0.5 ** (power/1e18)
Inspired by: https://github.com/balancer-labs/balancer-core/blob/master/contracts/BNum.sol#L128
"""
intpow: uint256 = power / 10**18
otherpow: uint256 = power - intpow * 10**18
if intpow > 59:
return 0
result: uint256 = 10**18 / (2**intpow)
if otherpow == 0:
return result
term: uint256 = 10**18
x: uint256 = 5 * 10**17
S: uint256 = 10**18
neg: bool = False
for i in range(1, 256):
K: uint256 = i * 10**18
c: uint256 = K - 10**18
if otherpow > c:
c = otherpow - c
neg = not neg
else:
c -= otherpow
term = term * (c * x / 10**18) / K
if neg:
S -= term
else:
S += term
if term < EXP_PRECISION:
return result * S / 10**18
raise "Did not converge"
### end of Math functions
@external
@view
def token() -> address:
return token
@external
@view
def coins(i: uint256) -> address:
_coins: address[N_COINS] = coins
return _coins[i]
@internal
@view
def xp() -> uint256[N_COINS]:
return [self.balances[0] * PRECISIONS[0],
self.balances[1] * PRECISIONS[1] * self.price_scale / PRECISION]
@view
@internal
def _A_gamma() -> uint256[2]:
t1: uint256 = self.future_A_gamma_time
A_gamma_1: uint256 = self.future_A_gamma
gamma1: uint256 = bitwise_and(A_gamma_1, 2**128-1)
A1: uint256 = shift(A_gamma_1, -128)
if block.timestamp < t1:
# handle ramping up and down of A
A_gamma_0: uint256 = self.initial_A_gamma
t0: uint256 = self.initial_A_gamma_time
# Less readable but more compact way of writing and converting to uint256
# gamma0: uint256 = bitwise_and(A_gamma_0, 2**128-1)
# A0: uint256 = shift(A_gamma_0, -128)
# A1 = A0 + (A1 - A0) * (block.timestamp - t0) / (t1 - t0)
# gamma1 = gamma0 + (gamma1 - gamma0) * (block.timestamp - t0) / (t1 - t0)
t1 -= t0
t0 = block.timestamp - t0
t2: uint256 = t1 - t0
A1 = (shift(A_gamma_0, -128) * t2 + A1 * t0) / t1
gamma1 = (bitwise_and(A_gamma_0, 2**128-1) * t2 + gamma1 * t0) / t1
return [A1, gamma1]
@view
@external
def A() -> uint256:
return self._A_gamma()[0]
@view
@external
def gamma() -> uint256:
return self._A_gamma()[1]
@internal
@view
def _fee(xp: uint256[N_COINS]) -> uint256:
"""
f = fee_gamma / (fee_gamma + (1 - K))
where
K = prod(x) / (sum(x) / N)**N
(all normalized to 1e18)
"""
fee_gamma: uint256 = self.fee_gamma
f: uint256 = xp[0] + xp[1] # sum
f = fee_gamma * 10**18 / (
fee_gamma + 10**18 - (10**18 * N_COINS**N_COINS) * xp[0] / f * xp[1] / f
)
return (self.mid_fee * f + self.out_fee * (10**18 - f)) / 10**18
@external
@view
def fee() -> uint256:
return self._fee(self.xp())
@internal
@view
def get_xcp(D: uint256) -> uint256:
x: uint256[N_COINS] = [D / N_COINS, D * PRECISION / (self.price_scale * N_COINS)]
return self.geometric_mean(x, True)
@external
@view
def get_virtual_price() -> uint256:
return 10**18 * self.get_xcp(self.D) / CurveToken(token).totalSupply()
@internal
def _claim_admin_fees():
A_gamma: uint256[2] = self._A_gamma()
xcp_profit: uint256 = self.xcp_profit
xcp_profit_a: uint256 = self.xcp_profit_a
# Gulp here
_coins: address[N_COINS] = coins
for i in range(N_COINS):
if i == ETH_INDEX:
self.balances[i] = self.balance
else:
self.balances[i] = ERC20(_coins[i]).balanceOf(self)
vprice: uint256 = self.virtual_price
if xcp_profit > xcp_profit_a:
fees: uint256 = (xcp_profit - xcp_profit_a) * self.admin_fee / (2 * 10**10)
if fees > 0:
receiver: address = self.admin_fee_receiver
if receiver != ZERO_ADDRESS:
frac: uint256 = vprice * 10**18 / (vprice - fees) - 10**18
claimed: uint256 = CurveToken(token).mint_relative(receiver, frac)
xcp_profit -= fees*2
self.xcp_profit = xcp_profit
log ClaimAdminFee(receiver, claimed)
total_supply: uint256 = CurveToken(token).totalSupply()
# Recalculate D b/c we gulped
D: uint256 = self.newton_D(A_gamma[0], A_gamma[1], self.xp())
self.D = D
self.virtual_price = 10**18 * self.get_xcp(D) / total_supply
if xcp_profit > xcp_profit_a:
self.xcp_profit_a = xcp_profit
@internal
def tweak_price(A_gamma: uint256[2],_xp: uint256[N_COINS], p_i: uint256, new_D: uint256):
price_oracle: uint256 = self.price_oracle
last_prices: uint256 = self.last_prices
price_scale: uint256 = self.price_scale
last_prices_timestamp: uint256 = self.last_prices_timestamp
p_new: uint256 = 0
if last_prices_timestamp < block.timestamp:
# MA update required
ma_half_time: uint256 = self.ma_half_time
alpha: uint256 = self.halfpow((block.timestamp - last_prices_timestamp) * 10**18 / ma_half_time)
price_oracle = (last_prices * (10**18 - alpha) + price_oracle * alpha) / 10**18
self.price_oracle = price_oracle
self.last_prices_timestamp = block.timestamp
D_unadjusted: uint256 = new_D # Withdrawal methods know new D already
if new_D == 0:
# We will need this a few times (35k gas)
D_unadjusted = self.newton_D(A_gamma[0], A_gamma[1], _xp)
if p_i > 0:
last_prices = p_i
else:
# calculate real prices
__xp: uint256[N_COINS] = _xp
dx_price: uint256 = __xp[0] / 10**6
__xp[0] += dx_price
last_prices = price_scale * dx_price / (_xp[1] - self.newton_y(A_gamma[0], A_gamma[1], __xp, D_unadjusted, 1))
self.last_prices = last_prices
total_supply: uint256 = CurveToken(token).totalSupply()
old_xcp_profit: uint256 = self.xcp_profit
old_virtual_price: uint256 = self.virtual_price
# Update profit numbers without price adjustment first
xp: uint256[N_COINS] = [D_unadjusted / N_COINS, D_unadjusted * PRECISION / (N_COINS * price_scale)]
xcp_profit: uint256 = 10**18
virtual_price: uint256 = 10**18
if old_virtual_price > 0:
xcp: uint256 = self.geometric_mean(xp, True)
virtual_price = 10**18 * xcp / total_supply
xcp_profit = old_xcp_profit * virtual_price / old_virtual_price
t: uint256 = self.future_A_gamma_time
if virtual_price < old_virtual_price and t == 0:
raise "Loss"
if t == 1:
self.future_A_gamma_time = 0
self.xcp_profit = xcp_profit
norm: uint256 = price_oracle * 10**18 / price_scale
if norm > 10**18:
norm -= 10**18
else:
norm = 10**18 - norm
adjustment_step: uint256 = max(self.adjustment_step, norm / 10)
needs_adjustment: bool = self.not_adjusted
# if not needs_adjustment and (virtual_price-10**18 > (xcp_profit-10**18)/2 + self.allowed_extra_profit):
# (re-arrange for gas efficiency)
if not needs_adjustment and (virtual_price * 2 - 10**18 > xcp_profit + 2*self.allowed_extra_profit) and (norm > adjustment_step) and (old_virtual_price > 0):
needs_adjustment = True
self.not_adjusted = True
if needs_adjustment:
if norm > adjustment_step and old_virtual_price > 0:
p_new = (price_scale * (norm - adjustment_step) + adjustment_step * price_oracle) / norm
# Calculate balances*prices
xp = [_xp[0], _xp[1] * p_new / price_scale]
# Calculate "extended constant product" invariant xCP and virtual price
D: uint256 = self.newton_D(A_gamma[0], A_gamma[1], xp)
xp = [D / N_COINS, D * PRECISION / (N_COINS * p_new)]
# We reuse old_virtual_price here but it's not old anymore
old_virtual_price = 10**18 * self.geometric_mean(xp, True) / total_supply
# Proceed if we've got enough profit
# if (old_virtual_price > 10**18) and (2 * (old_virtual_price - 10**18) > xcp_profit - 10**18):
if (old_virtual_price > 10**18) and (2 * old_virtual_price - 10**18 > xcp_profit):
self.price_scale = p_new
self.D = D
self.virtual_price = old_virtual_price
return
else:
self.not_adjusted = False
# Can instead do another flag variable if we want to save bytespace
self.D = D_unadjusted
self.virtual_price = virtual_price
self._claim_admin_fees()
return
# If we are here, the price_scale adjustment did not happen
# Still need to update the profit counter and D
self.D = D_unadjusted
self.virtual_price = virtual_price
# norm appeared < adjustment_step after
if needs_adjustment:
self.not_adjusted = False
self._claim_admin_fees()
@internal
def _exchange(sender: address, mvalue: uint256, i: uint256, j: uint256, dx: uint256, min_dy: uint256, use_eth: bool) -> uint256:
assert not self.is_killed # dev: the pool is killed
assert i != j # dev: coin index out of range
assert i < N_COINS # dev: coin index out of range
assert j < N_COINS # dev: coin index out of range
assert dx > 0 # dev: do not exchange 0 coins
A_gamma: uint256[2] = self._A_gamma()
xp: uint256[N_COINS] = self.balances
p: uint256 = 0
dy: uint256 = 0
_coins: address[N_COINS] = coins
if use_eth and i == ETH_INDEX:
assert mvalue == dx # dev: incorrect eth amount
else:
assert mvalue == 0 # dev: nonzero eth amount
assert ERC20(_coins[i]).transferFrom(sender, self, dx)
if i == ETH_INDEX:
WETH(_coins[i]).withdraw(dx)
y: uint256 = xp[j]
x0: uint256 = xp[i]
xp[i] = x0 + dx
self.balances[i] = xp[i]
price_scale: uint256 = self.price_scale
xp = [xp[0] * PRECISIONS[0], xp[1] * price_scale * PRECISIONS[1] / PRECISION]
prec_i: uint256 = PRECISIONS[0]
prec_j: uint256 = PRECISIONS[1]
if i == 1:
prec_i = PRECISIONS[1]
prec_j = PRECISIONS[0]
# In case ramp is happening
t: uint256 = self.future_A_gamma_time
if t > 0:
x0 *= prec_i
if i > 0:
x0 = x0 * price_scale / PRECISION
x1: uint256 = xp[i] # Back up old value in xp
xp[i] = x0
self.D = self.newton_D(A_gamma[0], A_gamma[1], xp)
xp[i] = x1 # And restore
if block.timestamp >= t:
self.future_A_gamma_time = 1
dy = xp[j] - self.newton_y(A_gamma[0], A_gamma[1], xp, self.D, j)
# Not defining new "y" here to have less variables / make subsequent calls cheaper
xp[j] -= dy
dy -= 1
if j > 0:
dy = dy * PRECISION / price_scale
dy /= prec_j
dy -= self._fee(xp) * dy / 10**10
assert dy >= min_dy, "Slippage"
y -= dy
self.balances[j] = y
if use_eth and j == ETH_INDEX:
raw_call(sender, b"", value=dy)
else:
if j == ETH_INDEX:
WETH(_coins[j]).deposit(value=dy)
assert ERC20(_coins[j]).transfer(sender, dy)
y *= prec_j
if j > 0:
y = y * price_scale / PRECISION
xp[j] = y
# Calculate price
if dx > 10**5 and dy > 10**5:
_dx: uint256 = dx * prec_i
_dy: uint256 = dy * prec_j
if i == 0:
p = _dx * 10**18 / _dy
else: # j == 0
p = _dy * 10**18 / _dx
self.tweak_price(A_gamma, xp, p, 0)
log TokenExchange(sender, i, dx, j, dy)
return dy
@payable
@external
@nonreentrant('lock')
def exchange(i: uint256, j: uint256, dx: uint256, min_dy: uint256, use_eth: bool = False) -> uint256:
"""
Exchange using WETH by default
"""
return self._exchange(msg.sender, msg.value, i, j, dx, min_dy, use_eth)
@payable
@external
@nonreentrant('lock')
def exchange_underlying(i: uint256, j: uint256, dx: uint256, min_dy: uint256) -> uint256:
"""
Exchange using ETH
"""
return self._exchange(msg.sender, msg.value, i, j, dx, min_dy, True)
@external
@view
def get_dy(i: uint256, j: uint256, dx: uint256) -> uint256:
assert i != j # dev: same input and output coin
assert i < N_COINS # dev: coin index out of range
assert j < N_COINS # dev: coin index out of range
price_scale: uint256 = self.price_scale * PRECISIONS[1]
xp: uint256[N_COINS] = self.balances
A_gamma: uint256[2] = self._A_gamma()
D: uint256 = self.D
if self.future_A_gamma_time > 0:
D = self.newton_D(A_gamma[0], A_gamma[1], self.xp())
xp[i] += dx
xp = [xp[0] * PRECISIONS[0], xp[1] * price_scale / PRECISION]
y: uint256 = self.newton_y(A_gamma[0], A_gamma[1], xp, D, j)
dy: uint256 = xp[j] - y - 1
xp[j] = y
if j > 0:
dy = dy * PRECISION / price_scale
else:
dy /= PRECISIONS[0]
dy -= self._fee(xp) * dy / 10**10
return dy
@view
@internal
def _calc_token_fee(amounts: uint256[N_COINS], xp: uint256[N_COINS]) -> uint256:
# fee = sum(amounts_i - avg(amounts)) * fee' / sum(amounts)
fee: uint256 = self._fee(xp) * N_COINS / (4 * (N_COINS-1))
S: uint256 = 0
for _x in amounts:
S += _x
avg: uint256 = S / N_COINS
Sdiff: uint256 = 0
for _x in amounts:
if _x > avg:
Sdiff += _x - avg
else:
Sdiff += avg - _x
return fee * Sdiff / S + NOISE_FEE
@payable
@external
@nonreentrant('lock')
def add_liquidity(amounts: uint256[N_COINS], min_mint_amount: uint256, use_eth: bool = False) -> uint256:
assert not self.is_killed # dev: the pool is killed
assert amounts[0] > 0 or amounts[1] > 0 # dev: no coins to add
A_gamma: uint256[2] = self._A_gamma()
_coins: address[N_COINS] = coins
xp: uint256[N_COINS] = self.balances
amountsp: uint256[N_COINS] = empty(uint256[N_COINS])
xx: uint256[N_COINS] = empty(uint256[N_COINS])
d_token: uint256 = 0
d_token_fee: uint256 = 0
old_D: uint256 = 0
xp_old: uint256[N_COINS] = xp
for i in range(N_COINS):
bal: uint256 = xp[i] + amounts[i]
xp[i] = bal
self.balances[i] = bal
xx = xp
price_scale: uint256 = self.price_scale * PRECISIONS[1]
xp = [xp[0] * PRECISIONS[0], xp[1] * price_scale / PRECISION]
xp_old = [xp_old[0] * PRECISIONS[0], xp_old[1] * price_scale / PRECISION]
if not use_eth:
assert msg.value == 0 # dev: nonzero eth amount
for i in range(N_COINS):
if use_eth and i == ETH_INDEX:
assert msg.value == amounts[i] # dev: incorrect eth amount
if amounts[i] > 0:
if (not use_eth) or (i != ETH_INDEX):
assert ERC20(_coins[i]).transferFrom(msg.sender, self, amounts[i])
if i == ETH_INDEX:
WETH(_coins[i]).withdraw(amounts[i])
amountsp[i] = xp[i] - xp_old[i]
t: uint256 = self.future_A_gamma_time
if t > 0:
old_D = self.newton_D(A_gamma[0], A_gamma[1], xp_old)
if block.timestamp >= t:
self.future_A_gamma_time = 1
else:
old_D = self.D
D: uint256 = self.newton_D(A_gamma[0], A_gamma[1], xp)
token_supply: uint256 = CurveToken(token).totalSupply()
if old_D > 0:
d_token = token_supply * D / old_D - token_supply
else:
d_token = self.get_xcp(D) # making initial virtual price equal to 1
assert d_token > 0 # dev: nothing minted
if old_D > 0:
d_token_fee = self._calc_token_fee(amountsp, xp) * d_token / 10**10 + 1
d_token -= d_token_fee
token_supply += d_token
CurveToken(token).mint(msg.sender, d_token)
# Calculate price
# p_i * (dx_i - dtoken / token_supply * xx_i) = sum{k!=i}(p_k * (dtoken / token_supply * xx_k - dx_k))
# Simplified for 2 coins
p: uint256 = 0
if d_token > 10**5:
if amounts[0] == 0 or amounts[1] == 0:
S: uint256 = 0
precision: uint256 = 0
ix: uint256 = 0
if amounts[0] == 0:
S = xx[0] * PRECISIONS[0]
precision = PRECISIONS[1]
ix = 1
else:
S = xx[1] * PRECISIONS[1]
precision = PRECISIONS[0]
S = S * d_token / token_supply
p = S * PRECISION / (amounts[ix] * precision - d_token * xx[ix] * precision / token_supply)
if ix == 0:
p = (10**18)**2 / p
self.tweak_price(A_gamma, xp, p, D)
else:
self.D = D
self.virtual_price = 10**18
self.xcp_profit = 10**18
CurveToken(token).mint(msg.sender, d_token)
assert d_token >= min_mint_amount, "Slippage"
log AddLiquidity(msg.sender, amounts, d_token_fee, token_supply)
return d_token
@external
@nonreentrant('lock')
def remove_liquidity(_amount: uint256, min_amounts: uint256[N_COINS], use_eth: bool = False):
"""
This withdrawal method is very safe, does no complex math
"""
_coins: address[N_COINS] = coins
total_supply: uint256 = CurveToken(token).totalSupply()
CurveToken(token).burnFrom(msg.sender, _amount)
balances: uint256[N_COINS] = self.balances
amount: uint256 = _amount - 1 # Make rounding errors favoring other LPs a tiny bit
for i in range(N_COINS):
d_balance: uint256 = balances[i] * amount / total_supply
assert d_balance >= min_amounts[i]
self.balances[i] = balances[i] - d_balance
balances[i] = d_balance # now it's the amounts going out
if use_eth and i == ETH_INDEX:
raw_call(msg.sender, b"", value=d_balance)
else:
if i == ETH_INDEX:
WETH(_coins[i]).deposit(value=d_balance)
assert ERC20(_coins[i]).transfer(msg.sender, d_balance)
D: uint256 = self.D
self.D = D - D * amount / total_supply
log RemoveLiquidity(msg.sender, balances, total_supply - _amount)
@view
@external
def calc_token_amount(amounts: uint256[N_COINS]) -> uint256:
token_supply: uint256 = CurveToken(token).totalSupply()
price_scale: uint256 = self.price_scale * PRECISIONS[1]
A_gamma: uint256[2] = self._A_gamma()
xp: uint256[N_COINS] = self.xp()
amountsp: uint256[N_COINS] = [
amounts[0] * PRECISIONS[0],
amounts[1] * price_scale / PRECISION]
D0: uint256 = self.D
if self.future_A_gamma_time > 0:
D0 = self.newton_D(A_gamma[0], A_gamma[1], xp)
xp[0] += amountsp[0]
xp[1] += amountsp[1]
D: uint256 = self.newton_D(A_gamma[0], A_gamma[1], xp)
d_token: uint256 = token_supply * D / D0 - token_supply
d_token -= self._calc_token_fee(amountsp, xp) * d_token / 10**10 + 1
return d_token
@internal
@view
def _calc_withdraw_one_coin(A_gamma: uint256[2], token_amount: uint256, i: uint256, update_D: bool,
calc_price: bool) -> (uint256, uint256, uint256, uint256[N_COINS]):
token_supply: uint256 = CurveToken(token).totalSupply()
assert token_amount <= token_supply # dev: token amount more than supply
assert i < N_COINS # dev: coin out of range
xx: uint256[N_COINS] = self.balances
D0: uint256 = 0
price_scale_i: uint256 = self.price_scale * PRECISIONS[1]
xp: uint256[N_COINS] = [xx[0] * PRECISIONS[0], xx[1] * price_scale_i / PRECISION]
if i == 0:
price_scale_i = PRECISION * PRECISIONS[0]
if update_D:
D0 = self.newton_D(A_gamma[0], A_gamma[1], xp)
else:
D0 = self.D
D: uint256 = D0
# Charge the fee on D, not on y, e.g. reducing invariant LESS than charging the user
fee: uint256 = self._fee(xp)
dD: uint256 = token_amount * D / token_supply
D -= (dD - (fee * dD / (2 * 10**10) + 1))
y: uint256 = self.newton_y(A_gamma[0], A_gamma[1], xp, D, i)
dy: uint256 = (xp[i] - y) * PRECISION / price_scale_i
xp[i] = y
# Price calc
p: uint256 = 0
if calc_price and dy > 10**5 and token_amount > 10**5:
# p_i = dD / D0 * sum'(p_k * x_k) / (dy - dD / D0 * y0)
S: uint256 = 0
precision: uint256 = PRECISIONS[0]
if i == 1:
S = xx[0] * PRECISIONS[0]
precision = PRECISIONS[1]
else:
S = xx[1] * PRECISIONS[1]
S = S * dD / D0
p = S * PRECISION / (dy * precision - dD * xx[i] * precision / D0)
if i == 0:
p = (10**18)**2 / p
return dy, p, D, xp
@view
@external
def calc_withdraw_one_coin(token_amount: uint256, i: uint256) -> uint256:
return self._calc_withdraw_one_coin(self._A_gamma(), token_amount, i, True, False)[0]
@external
@nonreentrant('lock')
def remove_liquidity_one_coin(token_amount: uint256, i: uint256, min_amount: uint256, use_eth: bool = False) -> uint256:
assert not self.is_killed # dev: the pool is killed
A_gamma: uint256[2] = self._A_gamma()
dy: uint256 = 0
D: uint256 = 0
p: uint256 = 0
xp: uint256[N_COINS] = empty(uint256[N_COINS])
future_A_gamma_time: uint256 = self.future_A_gamma_time
dy, p, D, xp = self._calc_withdraw_one_coin(A_gamma, token_amount, i, (future_A_gamma_time > 0), True)
assert dy >= min_amount, "Slippage"
if block.timestamp >= future_A_gamma_time:
self.future_A_gamma_time = 1
self.balances[i] -= dy
CurveToken(token).burnFrom(msg.sender, token_amount)
_coins: address[N_COINS] = coins
if use_eth and i == ETH_INDEX:
raw_call(msg.sender, b"", value=dy)
else:
if i == ETH_INDEX:
WETH(_coins[i]).deposit(value=dy)
assert ERC20(_coins[i]).transfer(msg.sender, dy)
self.tweak_price(A_gamma, xp, p, D)
log RemoveLiquidityOne(msg.sender, token_amount, i, dy)
return dy
@external
@nonreentrant('lock')
def claim_admin_fees():
self._claim_admin_fees()
# Admin parameters
@external
def ramp_A_gamma(future_A: uint256, future_gamma: uint256, future_time: uint256):
assert msg.sender == self.owner # dev: only owner
assert block.timestamp > self.initial_A_gamma_time + (MIN_RAMP_TIME-1)
assert future_time > block.timestamp + (MIN_RAMP_TIME-1) # dev: insufficient time
A_gamma: uint256[2] = self._A_gamma()
initial_A_gamma: uint256 = shift(A_gamma[0], 128)
initial_A_gamma = bitwise_or(initial_A_gamma, A_gamma[1])
assert future_A > MIN_A-1
assert future_A < MAX_A+1
assert future_gamma > MIN_GAMMA-1
assert future_gamma < MAX_GAMMA+1
ratio: uint256 = 10**18 * future_A / A_gamma[0]
assert ratio < 10**18 * MAX_A_CHANGE + 1
assert ratio > 10**18 / MAX_A_CHANGE - 1
ratio = 10**18 * future_gamma / A_gamma[1]
assert ratio < 10**18 * MAX_A_CHANGE + 1
assert ratio > 10**18 / MAX_A_CHANGE - 1
self.initial_A_gamma = initial_A_gamma
self.initial_A_gamma_time = block.timestamp
future_A_gamma: uint256 = shift(future_A, 128)
future_A_gamma = bitwise_or(future_A_gamma, future_gamma)
self.future_A_gamma_time = future_time
self.future_A_gamma = future_A_gamma
log RampAgamma(A_gamma[0], future_A, A_gamma[1], future_gamma, block.timestamp, future_time)
@external
def stop_ramp_A_gamma():
assert msg.sender == self.owner # dev: only owner
A_gamma: uint256[2] = self._A_gamma()
current_A_gamma: uint256 = shift(A_gamma[0], 128)
current_A_gamma = bitwise_or(current_A_gamma, A_gamma[1])
self.initial_A_gamma = current_A_gamma
self.future_A_gamma = current_A_gamma
self.initial_A_gamma_time = block.timestamp
self.future_A_gamma_time = block.timestamp
# now (block.timestamp < t1) is always False, so we return saved A
log StopRampA(A_gamma[0], A_gamma[1], block.timestamp)
@external
def commit_new_parameters(
_new_mid_fee: uint256,
_new_out_fee: uint256,
_new_admin_fee: uint256,
_new_fee_gamma: uint256,
_new_allowed_extra_profit: uint256,
_new_adjustment_step: uint256,
_new_ma_half_time: uint256,
):
assert msg.sender == self.owner # dev: only owner
assert self.admin_actions_deadline == 0 # dev: active action
new_mid_fee: uint256 = _new_mid_fee
new_out_fee: uint256 = _new_out_fee
new_admin_fee: uint256 = _new_admin_fee
new_fee_gamma: uint256 = _new_fee_gamma
new_allowed_extra_profit: uint256 = _new_allowed_extra_profit
new_adjustment_step: uint256 = _new_adjustment_step
new_ma_half_time: uint256 = _new_ma_half_time
# Fees
if new_out_fee < MAX_FEE+1:
assert new_out_fee > MIN_FEE-1 # dev: fee is out of range
else:
new_out_fee = self.out_fee
if new_mid_fee > MAX_FEE:
new_mid_fee = self.mid_fee
assert new_mid_fee <= new_out_fee # dev: mid-fee is too high
if new_admin_fee > MAX_ADMIN_FEE:
new_admin_fee = self.admin_fee
# AMM parameters
if new_fee_gamma < 10**18:
assert new_fee_gamma > 0 # dev: fee_gamma out of range [1 .. 10**18]
else:
new_fee_gamma = self.fee_gamma
if new_allowed_extra_profit > 10**18:
new_allowed_extra_profit = self.allowed_extra_profit
if new_adjustment_step > 10**18:
new_adjustment_step = self.adjustment_step
# MA
if new_ma_half_time < 7*86400:
assert new_ma_half_time > 0 # dev: MA time should be longer than 1 second
else:
new_ma_half_time = self.ma_half_time
_deadline: uint256 = block.timestamp + ADMIN_ACTIONS_DELAY
self.admin_actions_deadline = _deadline
self.future_admin_fee = new_admin_fee
self.future_mid_fee = new_mid_fee
self.future_out_fee = new_out_fee
self.future_fee_gamma = new_fee_gamma
self.future_allowed_extra_profit = new_allowed_extra_profit
self.future_adjustment_step = new_adjustment_step
self.future_ma_half_time = new_ma_half_time
log CommitNewParameters(_deadline, new_admin_fee, new_mid_fee, new_out_fee,
new_fee_gamma,
new_allowed_extra_profit, new_adjustment_step,
new_ma_half_time)
@external
@nonreentrant('lock')
def apply_new_parameters():
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
admin_fee: uint256 = self.future_admin_fee
if self.admin_fee != admin_fee:
self._claim_admin_fees()
self.admin_fee = admin_fee
mid_fee: uint256 = self.future_mid_fee
self.mid_fee = mid_fee
out_fee: uint256 = self.future_out_fee
self.out_fee = out_fee
fee_gamma: uint256 = self.future_fee_gamma
self.fee_gamma = fee_gamma
allowed_extra_profit: uint256 = self.future_allowed_extra_profit
self.allowed_extra_profit = allowed_extra_profit
adjustment_step: uint256 = self.future_adjustment_step
self.adjustment_step = adjustment_step
ma_half_time: uint256 = self.future_ma_half_time
self.ma_half_time = ma_half_time
log NewParameters(admin_fee, mid_fee, out_fee,
fee_gamma,
allowed_extra_profit, adjustment_step,
ma_half_time)
@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
@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
@external
def set_admin_fee_receiver(_admin_fee_receiver: address):
assert msg.sender == self.owner # dev: only owner
self.admin_fee_receiver = _admin_fee_receiver
@internal
@pure
def sqrt_int(x: uint256) -> uint256:
"""
Originating from: https://github.com/vyperlang/vyper/issues/1266
"""
if x == 0:
return 0
z: uint256 = (x + 10**18) / 2
y: uint256 = x
for i in range(256):
if z == y:
return y
y = z
z = (x * 10**18 / z + z) / 2
raise "Did not converge"
@external
@view
def lp_price() -> uint256:
"""
Approximate LP token price
"""
max_price: uint256 = 2 * self.virtual_price * self.sqrt_int(self.price_oracle) / 10**18
return max_price
[{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"uint256","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"uint256","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":"fee","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":"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_index","type":"uint256","indexed":false},{"name":"coin_amount","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":"CommitNewParameters","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"admin_fee","type":"uint256","indexed":false},{"name":"mid_fee","type":"uint256","indexed":false},{"name":"out_fee","type":"uint256","indexed":false},{"name":"fee_gamma","type":"uint256","indexed":false},{"name":"allowed_extra_profit","type":"uint256","indexed":false},{"name":"adjustment_step","type":"uint256","indexed":false},{"name":"ma_half_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewParameters","inputs":[{"name":"admin_fee","type":"uint256","indexed":false},{"name":"mid_fee","type":"uint256","indexed":false},{"name":"out_fee","type":"uint256","indexed":false},{"name":"fee_gamma","type":"uint256","indexed":false},{"name":"allowed_extra_profit","type":"uint256","indexed":false},{"name":"adjustment_step","type":"uint256","indexed":false},{"name":"ma_half_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampAgamma","inputs":[{"name":"initial_A","type":"uint256","indexed":false},{"name":"future_A","type":"uint256","indexed":false},{"name":"initial_gamma","type":"uint256","indexed":false},{"name":"future_gamma","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":"current_A","type":"uint256","indexed":false},{"name":"current_gamma","type":"uint256","indexed":false},{"name":"time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ClaimAdminFee","inputs":[{"name":"admin","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"owner","type":"address"},{"name":"admin_fee_receiver","type":"address"},{"name":"A","type":"uint256"},{"name":"gamma","type":"uint256"},{"name":"mid_fee","type":"uint256"},{"name":"out_fee","type":"uint256"},{"name":"allowed_extra_profit","type":"uint256"},{"name":"fee_gamma","type":"uint256"},{"name":"adjustment_step","type":"uint256"},{"name":"admin_fee","type":"uint256"},{"name":"ma_half_time","type":"uint256"},{"name":"initial_price","type":"uint256"},{"name":"_token","type":"address"},{"name":"_coins","type":"address[2]"}],"outputs":[]},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"view","type":"function","name":"token","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange_underlying","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"add_liquidity","inputs":[{"name":"amounts","type":"uint256[2]"},{"name":"min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"add_liquidity","inputs":[{"name":"amounts","type":"uint256[2]"},{"name":"min_mint_amount","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"min_amounts","type":"uint256[2]"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"min_amounts","type":"uint256[2]"},{"name":"use_eth","type":"bool"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"amounts","type":"uint256[2]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"},{"name":"min_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"},{"name":"min_amount","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_admin_fees","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"ramp_A_gamma","inputs":[{"name":"future_A","type":"uint256"},{"name":"future_gamma","type":"uint256"},{"name":"future_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A_gamma","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"commit_new_parameters","inputs":[{"name":"_new_mid_fee","type":"uint256"},{"name":"_new_out_fee","type":"uint256"},{"name":"_new_admin_fee","type":"uint256"},{"name":"_new_fee_gamma","type":"uint256"},{"name":"_new_allowed_extra_profit","type":"uint256"},{"name":"_new_adjustment_step","type":"uint256"},{"name":"_new_ma_half_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"apply_new_parameters","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revert_new_parameters","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"commit_transfer_ownership","inputs":[{"name":"_owner","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"apply_transfer_ownership","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revert_transfer_ownership","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"kill_me","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"unkill_me","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_admin_fee_receiver","inputs":[{"name":"_admin_fee_receiver","type":"address"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"lp_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_scale","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_oracle","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"last_prices","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"last_prices_timestamp","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_gamma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_gamma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"allowed_extra_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_allowed_extra_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"fee_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_fee_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"adjustment_step","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_adjustment_step","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_half_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_ma_half_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"mid_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"out_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_mid_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_out_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"future_owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"xcp_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"xcp_profit_a","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"is_killed","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"kill_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"transfer_ownership_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_actions_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee_receiver","inputs":[],"outputs":[{"name":"","type":"address"}]}]
[{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"uint256","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"uint256","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":"fee","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":"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_index","type":"uint256","indexed":false},{"name":"coin_amount","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":"CommitNewParameters","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"admin_fee","type":"uint256","indexed":false},{"name":"mid_fee","type":"uint256","indexed":false},{"name":"out_fee","type":"uint256","indexed":false},{"name":"fee_gamma","type":"uint256","indexed":false},{"name":"allowed_extra_profit","type":"uint256","indexed":false},{"name":"adjustment_step","type":"uint256","indexed":false},{"name":"ma_half_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewParameters","inputs":[{"name":"admin_fee","type":"uint256","indexed":false},{"name":"mid_fee","type":"uint256","indexed":false},{"name":"out_fee","type":"uint256","indexed":false},{"name":"fee_gamma","type":"uint256","indexed":false},{"name":"allowed_extra_profit","type":"uint256","indexed":false},{"name":"adjustment_step","type":"uint256","indexed":false},{"name":"ma_half_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampAgamma","inputs":[{"name":"initial_A","type":"uint256","indexed":false},{"name":"future_A","type":"uint256","indexed":false},{"name":"initial_gamma","type":"uint256","indexed":false},{"name":"future_gamma","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":"current_A","type":"uint256","indexed":false},{"name":"current_gamma","type":"uint256","indexed":false},{"name":"time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ClaimAdminFee","inputs":[{"name":"admin","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"owner","type":"address"},{"name":"admin_fee_receiver","type":"address"},{"name":"A","type":"uint256"},{"name":"gamma","type":"uint256"},{"name":"mid_fee","type":"uint256"},{"name":"out_fee","type":"uint256"},{"name":"allowed_extra_profit","type":"uint256"},{"name":"fee_gamma","type":"uint256"},{"name":"adjustment_step","type":"uint256"},{"name":"admin_fee","type":"uint256"},{"name":"ma_half_time","type":"uint256"},{"name":"initial_price","type":"uint256"},{"name":"_token","type":"address"},{"name":"_coins","type":"address[2]"}],"outputs":[]},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"view","type":"function","name":"token","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange_underlying","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"add_liquidity","inputs":[{"name":"amounts","type":"uint256[2]"},{"name":"min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"add_liquidity","inputs":[{"name":"amounts","type":"uint256[2]"},{"name":"min_mint_amount","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"min_amounts","type":"uint256[2]"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"min_amounts","type":"uint256[2]"},{"name":"use_eth","type":"bool"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"amounts","type":"uint256[2]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"},{"name":"min_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"},{"name":"min_amount","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_admin_fees","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"ramp_A_gamma","inputs":[{"name":"future_A","type":"uint256"},{"name":"future_gamma","type":"uint256"},{"name":"future_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A_gamma","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"commit_new_parameters","inputs":[{"name":"_new_mid_fee","type":"uint256"},{"name":"_new_out_fee","type":"uint256"},{"name":"_new_admin_fee","type":"uint256"},{"name":"_new_fee_gamma","type":"uint256"},{"name":"_new_allowed_extra_profit","type":"uint256"},{"name":"_new_adjustment_step","type":"uint256"},{"name":"_new_ma_half_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"apply_new_parameters","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revert_new_parameters","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"commit_transfer_ownership","inputs":[{"name":"_owner","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"apply_transfer_ownership","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revert_transfer_ownership","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"kill_me","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"unkill_me","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_admin_fee_receiver","inputs":[{"name":"_admin_fee_receiver","type":"address"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"lp_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_scale","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_oracle","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"last_prices","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"last_prices_timestamp","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_gamma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_gamma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"allowed_extra_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_allowed_extra_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"fee_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_fee_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"adjustment_step","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_adjustment_step","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_half_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_ma_half_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"mid_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"out_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_mid_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_out_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"future_owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"xcp_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"xcp_profit_a","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"is_killed","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"kill_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"transfer_ownership_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_actions_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee_receiver","inputs":[],"outputs":[{"name":"","type":"address"}]}]
6020615b206080396080518060a01c615b1b5760e05260206020615b20016080396080518060a01c615b1b57610100526020610180615b20016080396080518060a01c615b1b57610120526101a0615b20016020816080396080518060a01c615b1b57610140526020602082016080396080518060a01c615b1b57610160525060e051601a5560206040615b200160803960805160801b6101805260206060615b2001608039608051610180511761018052610180516005556101805160065560206080615b2001608039608051601155602060a0615b2001608039608051601255602060c0615b2001608039608051600955602060e0615b2001608039608051600b556020610100615b2001608039608051600d556020610120615b20016080396080516013556020610160615b20016080396080516001556020610160615b20016080396080516002556020610160615b2001608039608051600355426004556020610140615b2001608039608051600f55670de0b6b3a7640000601d5542624f1a008181830110615b1b578082019050905060215561010051602455610120516101a052610140516101c052610160516101e052604e601263313ce567610200526020610200600461021c610140515afa6101e2573d600060003e3d6000fd5b601f3d1115615b1b5761020051808210615b1b57808203905090501015615b1b57601263313ce567610200526020610200600461021c610140515afa61022d573d600060003e3d6000fd5b601f3d1115615b1b5761020051808210615b1b5780820390509050600a0a61028052604e601263313ce567610240526020610240600461025c610160515afa61027b573d600060003e3d6000fd5b601f3d1115615b1b5761024051808210615b1b57808203905090501015615b1b57601263313ce567610240526020610240600461025c610160515afa6102c6573d600060003e3d6000fd5b601f3d1115615b1b5761024051808210615b1b5780820390509050600a0a6102a052615ac956600436101561000d57612499565b60046000601c37600051635b41b908811861002d576000610cc052610048565b63394747c5811861008d576084358060011c6157d757610cc0525b6000546157d7576001600055336109a052346109c052608060046109e037610cc051610a6052610079610ce0614743565b610ce051610d00526020610d006000600055f35b6365b2489b81186100db576000546157d7576001600055336109a052346109c052608060046109e0376001610a60526100c7610cc0614743565b610cc051610ce0526020610ce06000600055f35b630b4c7e4d81186100f15760006109a05261010c565b63ee22be238118610a58576064358060011c6157d7576109a0525b6000546157d75760016000556020546157d75760006004351161013457600060243511610137565b60015b156157d757610147610a0061386d565b610a0080516109c05280602001516109e0525060803803602081608039608051610a0052602081602001608039608051610a205250601754610a4052601854610a605260e036610a8037610a4051610b6052610a6051610b8052610ba060006002818352015b610a40610ba05160028110156157d75760200201516020610ba051026004013581818301106157d75780820190509050610bc052610bc051610a40610ba05160028110156157d7576020020152610bc0516001610ba05160028110156157d757026017015581516001018083528114156101ad575050610a4051610ac052610a6051610ae0526001546020604038036020016080396080518082028215828483041417156157d75790509050610ba052610a40516020604038036080396080518082028215828483041417156157d75790509050610a4052610a6051610ba0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610a6052610b60516020604038036080396080518082028215828483041417156157d75790509050610b6052610b8051610ba0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610b80526109a05161031b57346157d7575b610bc060006002818352015b6109a05161033657600061033c565b610bc051155b15610353576020610bc051026004013534186157d7575b60006020610bc051026004013511156104a4576109a0511561037c576000610bc051141561037f565b60015b15610456576323b872dd610be05233610c005230610c20526020610bc0510260040135610c40526020610be06064610bfc6000610a00610bc05160028110156157d75760200201515af16103d8573d600060003e3d6000fd5b601f3d11156157d757610be051156157d757610bc05161045657632e1a7d4d610be0526020610bc0510260040135610c0052610a00610bc05160028110156157d75760200201513b156157d757600060006024610bfc6000610a00610bc05160028110156157d75760200201515af1610456573d600060003e3d6000fd5b610a40610bc05160028110156157d7576020020151610b60610bc05160028110156157d75760200201518082106157d75780820390509050610a80610bc05160028110156157d75760200201525b8151600101808352811415610327575050600854610bc0526000610bc051116104d357601954610b4052610516565b6109c051610200526109e05161022052610b605161024052610b8051610260526104fe610be0612666565b610be051610b4052610bc05142106105165760016008555b6109c051610200526109e05161022052610a405161024052610a605161026052610541610c00612666565b610c0051610be0526318160ddd610c20526020610c206004610c3c602060a038036080396080515afa610579573d600060003e3d6000fd5b601f3d11156157d757610c2051610c00526000610b4051116105b557610be051610200526105a8610c20613b2b565b610c2051610b00526105f9565b610c0051610be0518082028215828483041417156157d75790509050610b40518080156157d757820490509050610c00518082106157d75780820390509050610b00525b6000610b005111156157d7576000610b40511161068057610be051601955670de0b6b3a7640000601e55670de0b6b3a7640000601c556340c10f19610c205233610c4052610b0051610c60526020610c206044610c3c6000602060a038036080396080515af161066e573d600060003e3d6000fd5b601f3d11156157d757610c205061097a565b610a805161016052610aa05161018052610a40516101a052610a60516101c0526106ab610c2061501c565b610c2051610b00518082028215828483041417156157d757905090506402540be40080820490509050600181818301106157d75780820190509050610b2052610b008051610b20518082106157d75780820390509050815250610c008051610b005181818301106157d757808201905090508152506340c10f19610c205233610c4052610b0051610c60526020610c206044610c3c6000602060a038036080396080515af161075f573d600060003e3d6000fd5b601f3d11156157d757610c20506000610c2052620186a0610b0051111561094257600435156107915760243515610794565b60015b1561094257606036610c4037600435156107e857610ae0516020604038036020016080396080518082028215828483041417156157d75790509050610c4052602060403803608039608051610c605261082a565b610ac0516020604038036080396080518082028215828483041417156157d75790509050610c4052602060403803602001608039608051610c60526001610c80525b610c4051610b00518082028215828483041417156157d75790509050610c00518080156157d757820490509050610c4052610c4051670de0b6b3a76400008082028215828483041417156157d757905090506020610c80510260040135610c60518082028215828483041417156157d75790509050610b0051610ac0610c805160028110156157d75760200201518082028215828483041417156157d75790509050610c60518082028215828483041417156157d75790509050610c00518080156157d7578204905090508082106157d757808203905090508080156157d757820490509050610c2052610c8051610942576ec097ce7bc90715b34b9f1000000000610c20518080156157d757820490509050610c20525b6109c0516106a0526109e0516106c052610a40516106e052610a605161070052610c205161072052610be0516107405261097a613f35565b604435610b005110156109fe576008610c20527f536c697070616765000000000000000000000000000000000000000000000000610c4052610c2050610c205180610c4001818260206001820306601f82010390500336823750506308c379a0610be0526020610c0052610c205160206001820306601f8201039050604401610bfcfd5b337f540ab385f9b5d450a27404172caade516b3ba3f4be88239ac56a2ad1de2a1f5a600435610c2052602435610c4052610b2051610c6052610c0051610c80526080610c20a2610b0051610c20526020610c206000600055f35b63fc0c546a8118610a7d57346157d757602060a0380360803960805160e052602060e0f35b63c66106578118610acc57346157d7576080380360208160803960805160e052602081602001608039608051610100525060e060043560028110156157d7576020020151610120526020610120f35b63f446c1d08118610af657346157d757610ae76101c061386d565b6101c051610200526020610200f35b63b13739298118610b2357346157d757610b116101c061386d565b6101c060200151610200526020610200f35b63ddca3f438118610b7a57346157d757610b3e6101606137f3565b61016080516101c05280602001516101e052506101c05160e0526101e05161010052610b6b6101a06139e0565b6101a051610200526020610200f35b63bb7b8b808118610c1257346157d757670de0b6b3a764000060195461020052610ba5610280613b2b565b610280518082028215828483041417156157d757905090506318160ddd6102a05260206102a060046102bc602060a038036080396080515afa610bed573d600060003e3d6000fd5b601f3d11156157d7576102a0518080156157d7578204905090506102e05260206102e0f35b63556d6e9f8118610ef257346157d757602435600435146157d757600260043510156157d757600260243510156157d7576001546020604038036020016080396080518082028215828483041417156157d757905090506104a0526017546104c0526018546104e052610c8661054061386d565b610540805161050052806020015161052052506019546105405260006008541115610d0d57610500516105c052610520516105e052610cc66105606137f3565b610560805161060052806020015161062052506105c051610200526105e0516102205261060051610240526106205161026052610d046105a0612666565b6105a051610540525b6104c060043560028110156157d75760200201805160443581818301106157d757808201905090508152506104c0516020604038036080396080518082028215828483041417156157d757905090506104c0526104e0516104a0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090506104e0526105005160e05261052051610100526104c051610120526104e05161014052610540516101605260243561018052610dc9610580612df5565b61058051610560526104c060243560028110156157d7576020020151610560518082106157d7578082039050905060018082106157d7578082039050905061058052610560516104c060243560028110156157d7576020020152600060243511610e535761058080516020604038036080396080518080156157d757820490509050815250610e8a565b61058051670de0b6b3a76400008082028215828483041417156157d757905090506104a0518080156157d757820490509050610580525b61058080516104c05160e0526104e05161010052610ea96105a06139e0565b6105a051610580518082028215828483041417156157d757905090506402540be400808204905090508082106157d75780820390509050815250610580516105a05260206105a0f35b635b36389c8118610f0757600060e052610f21565b63269b5581811861126e576064358060011c6157d75760e0525b346157d7576000546157d7576001600055608038036020816080396080516101005260208160200160803960805161012052506318160ddd610160526020610160600461017c602060a038036080396080515afa610f84573d600060003e3d6000fd5b601f3d11156157d75761016051610140526379cc67906101605233610180526004356101a0526020610160604461017c6000602060a038036080396080515af1610fd3573d600060003e3d6000fd5b601f3d11156157d75761016050601754610160526018546101805260043560018082106157d757808203905090506101a0526101c060006002818352015b6101606101c05160028110156157d75760200201516101a0518082028215828483041417156157d75790509050610140518080156157d7578204905090506101e05260206101c05102602401356101e051106157d7576101606101c05160028110156157d75760200201516101e0518082106157d7578082039050905060016101c05160028110156157d75702601701556101e0516101606101c05160028110156157d757602002015260e0516110c95760006110cf565b6101c051155b611191576101c0516111325763d0e30db0610200526101006101c05160028110156157d75760200201513b156157d75760006000600461021c6101e0516101006101c05160028110156157d75760200201515af1611132573d600060003e3d6000fd5b63a9059cbb6102005233610220526101e051610240526020610200604461021c60006101006101c05160028110156157d75760200201515af161117a573d600060003e3d6000fd5b601f3d11156157d75761020051156157d7576111bc565b6000610200526102005060006000610200516102206101e051335af16111bc573d600060003e3d6000fd5b81516001018083528114156110115750506019546101c0526101c0516101c0516101a0518082028215828483041417156157d75790509050610140518080156157d7578204905090508082106157d75780820390509050601955337fdd3c0336a16f1b64f172b7bb0dad5b2b3c7c76f91e8c4aafd6aae60dce800153610160516101e0526101805161020052610140516004358082106157d757808203905090506102205260606101e0a26000600055005b638d8ea72781186114fa57346157d7576318160ddd6104c05260206104c060046104dc602060a038036080396080515afa6112ae573d600060003e3d6000fd5b601f3d11156157d7576104c0516104a0526001546020604038036020016080396080518082028215828483041417156157d757905090506104c0526112f461052061386d565b61052080516104e052806020015161050052506113126105606137f3565b610560805161052052806020015161054052506004356020604038036080396080518082028215828483041417156157d75790509050610560526024356104c0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610580526019546105a052600060085411156113c1576104e051610200526105005161022052610520516102405261054051610260526113b86105c0612666565b6105c0516105a0525b61052080516105605181818301106157d7578082019050905081525061054080516105805181818301106157d757808201905090508152506104e051610200526105005161022052610520516102405261054051610260526114246105e0612666565b6105e0516105c0526104a0516105c0518082028215828483041417156157d757905090506105a0518080156157d7578204905090506104a0518082106157d757808203905090506105e0526105e0805161056051610160526105805161018052610520516101a052610540516101c05261149f61060061501c565b610600516105e0518082028215828483041417156157d757905090506402540be40080820490509050600181818301106157d757808201905090508082106157d757808203905090508152506105e051610600526020610600f35b634fb08c5e811861158657346157d75761151561074061386d565b61074080516108205280602001516108405250604060046108603760016108a05260006108c052610820516104a052610840516104c052610860516104e05261088051610500526108a051610520526108c051610540526115776107806151a5565b610780516108e05260206108e0f35b63f1dc3cc9811861159c5760006109a0526115b7565b638f15b6b5811861190a576064358060011c6157d7576109a0525b346157d7576000546157d75760016000556020546157d7576115da610a0061386d565b610a0080516109c05280602001516109e0525060a036610a0037600854610aa0526109c0516104a0526109e0516104c052604060046104e0376000610aa051116105205260016105405261162f610ac06151a5565b610ac08051610a00526020810151610a40526040810151610a2052606081018051610a60528060200151610a80525050604435610a005110156116e3576008610ac0527f536c697070616765000000000000000000000000000000000000000000000000610ae052610ac050610ac05180610ae001818260206001820306601f82010390500336823750506308c379a0610a80526020610aa052610ac05160206001820306601f8201039050604401610a9cfd5b610aa05142106116f35760016008555b600160243560028110156157d757026017018054610a00518082106157d757808203905090508155506379cc6790610ac05233610ae052600435610b00526020610ac06044610adc6000602060a038036080396080515af161175a573d600060003e3d6000fd5b601f3d11156157d757610ac05060803803602081608039608051610ac052602081602001608039608051610ae052506109a05161179857600061179d565b602435155b61185b576024356117fd5763d0e30db0610b0052610ac060243560028110156157d75760200201513b156157d757600060006004610b1c610a0051610ac060243560028110156157d75760200201515af16117fd573d600060003e3d6000fd5b63a9059cbb610b005233610b2052610a0051610b40526020610b006044610b1c6000610ac060243560028110156157d75760200201515af1611844573d600060003e3d6000fd5b601f3d11156157d757610b0051156157d757611886565b6000610b0052610b005060006000610b0051610b20610a0051335af1611886573d600060003e3d6000fd5b6109c0516106a0526109e0516106c052610a60516106e052610a805161070052610a405161072052610a2051610740526118be613f35565b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a060406004610b0037610a0051610b40526060610b00a2610a0051610b00526020610b006000600055f35b63c93f49e8811861193557346157d7576000546157d757600160005561192e613bb0565b6000600055005b635e2480728118611b3157346157d757601a5433186157d7576007546201517f81818301106157d757808201905090504211156157d757426201517f81818301106157d7578082019050905060443511156157d75761199561020061386d565b61020080516101c05280602001516101e052506101c05160801b610200526101e051610200511761020052610f9f60043511156157d75763ee6b280160043510156157d7576402540be3ff60243511156157d75766470de4df82000160243510156157d757670de0b6b3a76400006004358082028215828483041417156157d757905090506101c0518080156157d75782049050905061022052678ac7230489e800016102205110156157d75767016345785d89ffff6102205111156157d757670de0b6b3a76400006024358082028215828483041417156157d757905090506101e0518080156157d75782049050905061022052678ac7230489e800016102205110156157d75767016345785d89ffff6102205111156157d757610200516005554260075560043560801b61024052602435610240511761024052604435600855610240516006557fe35f0559b0642164e286b30df2077ec3a05426617a25db7578fd20ba39a6cd056101c05161026052600435610280526101e0516102a0526024356102c052426102e0526044356103005260c0610260a1005b63244c7c2e8118611bd457346157d757601a5433186157d757611b5561020061386d565b61020080516101c05280602001516101e052506101c05160801b610200526101e051610200511761020052610200516005556102005160065542600755426008557f5f0e7fba3d100c9e19446e1c92fe436f0a9a22fe99669360e4fdd6d3de2fc2846101c051610220526101e0516102405242610260526060610220a1005b63a43c33518118611d9a57346157d757601a5433186157d7576023546157d75760e0600460e0376402540be4016101005110611c165760125461010052611c25565b6207a11f6101005111156157d7575b6402540be40060e0511115611c3b5760115460e0525b6101005160e051116157d7576402540be400610120511115611c5f57601354610120525b670de0b6b3a76400006101405110611c7d57600b5461014052611c8a565b60006101405111156157d7575b670de0b6b3a7640000610160511115611ca557600954610160525b670de0b6b3a7640000610180511115611cc057600d54610180525b62093a806101a05110611cd957600f546101a052611ce6565b60006101a05111156157d7575b426203f48081818301106157d757808201905090506101c0526101c0516023556101205160165560e0516014556101005160155561014051600c5561016051600a5561018051600e556101a0516010556101c0517f913fde9a37e1f8ab67876a4d0ce80790d764fcfc5692f4529526df9c6bdde553610120516101e05260e0516102005261010051610220526101405161024052610160516102605261018051610280526101a0516102a05260e06101e0a2005b632a7dd7cd8118611eb457346157d7576000546157d7576001600055601a5433186157d75760235442106157d7576000602354146157d75760006023556016546106a0526106a05160135414611dfa57611df2613bb0565b6106a0516013555b6014546106c0526106c0516011556015546106e0526106e051601255600c546107005261070051600b55600a546107205261072051600955600e546107405261074051600d556010546107605261076051600f557f1c65bbdc939f346e5d6f0bde1f072819947438d4fc7b182cc59c2f6dc55040876106a051610780526106c0516107a0526106e0516107c052610700516107e05261072051610800526107405161082052610760516108405260e0610780a16000600055005b63226840fb8118611ed457346157d757601a5433186157d7576000602355005b636b441a408118611f58576004358060a01c6157d75760e052346157d757601a5433186157d7576022546157d757426203f48081818301106157d75780820190509050610100526101005160225560e051601b5560e051610100517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb9356000610120a3005b636a1c05ae8118611fc157346157d757601a5433186157d75760225442106157d7576000602254146157d7576000602255601b5460e05260e051601a5560e0517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c6000610100a2005b6386fbf1938118611fe157346157d757601a5433186157d7576000602255005b63e3698853811861200b57346157d757601a5433186157d7574260215411156157d7576001602055005b633046f972811861202b57346157d757601a5433186157d7576000602055005b637242e524811861205a576004358060a01c6157d75760e052346157d757601a5433186157d75760e051602455005b6354f0f7d581186120cf57346157d7576002601e548082028215828483041417156157d7579050905060025460e0526120946101a061568a565b6101a0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061018052610180516101a05260206101a0f35b63b9e8c9fd81186120eb57346157d75760015460e052602060e0f35b6386fc88d3811861210757346157d75760025460e052602060e0f35b63c146bf94811861212357346157d75760035460e052602060e0f35b636112c747811861213f57346157d75760045460e052602060e0f35b63204fe3d5811861215b57346157d75760055460e052602060e0f35b63f30cfad5811861217757346157d75760065460e052602060e0f35b63e89876ff811861219357346157d75760075460e052602060e0f35b63f9ed959781186121af57346157d75760085460e052602060e0f35b6349fe9e7781186121cb57346157d75760095460e052602060e0f35b63727ced5781186121e757346157d757600a5460e052602060e0f35b6372d4f0e2811861220357346157d757600b5460e052602060e0f35b63d7c3dcbe811861221f57346157d757600c5460e052602060e0f35b63083812e5811861223b57346157d757600d5460e052602060e0f35b634ea12c7d811861225757346157d757600e5460e052602060e0f35b63662b6274811861227357346157d757600f5460e052602060e0f35b630c5e23d4811861228f57346157d75760105460e052602060e0f35b6392526c0c81186122ab57346157d75760115460e052602060e0f35b63ee8de67581186122c757346157d75760125460e052602060e0f35b63fee3f7f981186122e357346157d75760135460e052602060e0f35b637cf9aedc81186122ff57346157d75760145460e052602060e0f35b637d1b060c811861231b57346157d75760155460e052602060e0f35b63e3824462811861233757346157d75760165460e052602060e0f35b634903b0d1811861236357346157d757600160043560028110156157d757026017015460e052602060e0f35b630f529ba2811861237f57346157d75760195460e052602060e0f35b638da5cb5b811861239b57346157d757601a5460e052602060e0f35b631ec0cdc181186123b757346157d757601b5460e052602060e0f35b637ba1a74d81186123d357346157d757601c5460e052602060e0f35b630b7b594b81186123ef57346157d757601d5460e052602060e0f35b630c46b72a811861240b57346157d757601e5460e052602060e0f35b639c868ac0811861242757346157d75760205460e052602060e0f35b632a426896811861244357346157d75760215460e052602060e0f35b63e0a0b586811861245f57346157d75760225460e052602060e0f35b63405e28f8811861247b57346157d75760235460e052602060e0f35b636e42e4d2811861249757346157d75760245460e052602060e0f35b505b005b60e051610140526101005161016052610120516124b95760006124c3565b6101605161014051105b156124d857610100516101405260e051610160525b610140516101805260006101a0526101c0600060ff818352015b610180516101e0526101805161014051610160518082028215828483041417156157d75790509050610180518080156157d75782049050905081818301106157d75780820190509050600280820490509050610180526101e0516101805111612574576101e051610180518082106157d757808203905090506101a05261258f565b610180516101e0518082106157d757808203905090506101a0525b60016101a05111156125c657610180516101a051670de0b6b3a76400008082028215828483041417156157d75790509050106125c9565b60015b156125dc57505061018051815250612664565b81516001018083528114156124f257505060106101c0527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101e0526101c0506101c051806101e001818260206001820306601f82010390500336823750506308c379a06101805260206101a0526101c05160206001820306601f820103905060440161019cfd5b565b610f9f6102005111612679576000612684565b63ee6b280161020051105b156157d7576402540be3ff610220511161269f5760006126ad565b66470de4df82000161022051105b156157d7576102405161028052610260516102a0526102a0516102805110156126e1576102605161028052610240516102a0525b633b9ac9ff61028051116126f657600061270b565b6d314dc6448d9338c15b0a0000000161028051105b156157d757655af3107a3fff6102a051670de0b6b3a76400008082028215828483041417156157d75790509050610280518080156157d75782049050905011156157d75760026102805160e0526102a051610100526000610120526127716102e061249b565b6102e0518082028215828483041417156157d757905090506102c052610280516102a05181818301106157d757808201905090506102e052610300600060ff818352015b6102c05161032052673782dace9d900000610280518082028215828483041417156157d757905090506102c0518080156157d7578204905090506102a0518082028215828483041417156157d757905090506102c0518080156157d7578204905090506103405261022051670de0b6b3a764000081818301106157d757808201905090506103605261034051610360511161287b5761034051610360518082106157d75780820390509050600181818301106157d75780820190509050610360526128a8565b61036051610340518082106157d75780820390509050600181818301106157d75780820190509050610360525b670de0b6b3a76400006102c0518082028215828483041417156157d75790509050610220518080156157d757820490509050610360518082028215828483041417156157d75790509050610220518080156157d757820490509050610360518082028215828483041417156157d757905090506127108082028215828483041417156157d75790509050610200518080156157d75782049050905061038052673782dace9d900000610340518082028215828483041417156157d75790509050610360518080156157d7578204905090506103a0526102e0516102e0516103a0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905081818301106157d757808201905090506103805160028082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090506103a0516102c0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508082106157d757808203905090506103c0526102c0516103c0516102e05181818301106157d757808201905090508082028215828483041417156157d757905090506103c0518080156157d7578204905090506103e0526102c0516102c0518082028215828483041417156157d757905090506103c0518080156157d7578204905090506104005261034051670de0b6b3a764000011612b565761040080516102c051610380516103c0518080156157d7578204905090508082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061034051670de0b6b3a76400008082106157d757808203905090508082028215828483041417156157d75790509050610340518080156157d7578204905090508082106157d75780820390509050815250612bec565b61040080516102c051610380516103c0518080156157d7578204905090508082028215828483041417156157d75790509050670de0b6b3a764000080820490509050670de0b6b3a7640000610340518082106157d757808203905090508082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090508152505b610400516103e05111612c2157610400516103e0518082106157d757808203905090506002808204905090506102c052612c3c565b6103e051610400518082106157d757808203905090506102c0525b600061042052610320516102c05111612c6e57610320516102c0518082106157d7578082039050905061042052612c89565b6102c051610320518082106157d75780820390509050610420525b662386f26fc100006102c051808210612ca25781612ca4565b805b9050905061042051655af3107a40008082028215828483041417156157d757905090501015612d6b5761046060006002818352015b6020610460510261028001516104405261044051670de0b6b3a76400008082028215828483041417156157d757905090506102c0518080156157d75782049050905061048052662386f26fc0ffff6104805111612d37576000612d47565b68056bc75e2d6310000161048051105b156157d7578151600101808352811415612cd957505050506102c051815250612df3565b81516001018083528114156127b55750506010610300527f446964206e6f7420636f6e7665726765000000000000000000000000000000006103205261030050610300518061032001818260206001820306601f82010390500336823750506308c379a06102c05260206102e0526103005160206001820306601f82010390506044016102dcfd5b565b610f9f60e05111612e07576000612e11565b63ee6b280160e051105b156157d7576402540be3ff6101005111612e2c576000612e3a565b66470de4df82000161010051105b156157d75767016345785d89ffff6101605111612e58576000612e6d565b6d314dc6448d9338c15b0a0000000161016051105b156157d7576101206001610180518082106157d7578082039050905060028110156157d75760200201516101a0527001000000000000000000000000000000006101605110156157d7576002610160510a6101a05160048082028215828483041417156157d757905090508080156157d7578204905090506101c052671bc16d674ec800006101a0518082028215828483041417156157d75790509050610160518080156157d7578204905090506101e05266470de4df81ffff6101e05111612f37576000612f47565b680ad78ebc5ac62000016101e051105b156157d7576101a051655af3107a40008082049050905061016051655af3107a400080820490509050808210612f7d5781612f7f565b805b905090506064808210612f925781612f94565b805b9050905061020052610220600060ff818352015b6101c051610240526101e0516101c0518082028215828483041417156157d7579050905060028082028215828483041417156157d75790509050610160518080156157d757820490509050610260526101a0516101c05181818301106157d757808201905090506102805261010051670de0b6b3a764000081818301106157d757808201905090506102a052610260516102a0511161307257610260516102a0518082106157d75780820390509050600181818301106157d757808201905090506102a05261309f565b6102a051610260518082106157d75780820390509050600181818301106157d757808201905090506102a0525b670de0b6b3a7640000610160518082028215828483041417156157d75790509050610100518080156157d7578204905090506102a0518082028215828483041417156157d75790509050610100518080156157d7578204905090506102a0518082028215828483041417156157d757905090506127108082028215828483041417156157d7579050905060e0518080156157d7578204905090506102c052670de0b6b3a7640000671bc16d674ec80000610260518082028215828483041417156157d757905090506102a0518080156157d75782049050905081818301106157d757808201905090506102e052670de0b6b3a76400006101c0518082028215828483041417156157d75790509050610280516102e0518082028215828483041417156157d7579050905081818301106157d757808201905090506102c05181818301106157d7578082019050905061030052610160516102e0518082028215828483041417156157d757905090506103205261032051610300511061323d576103008051610320518082106157d75780820390509050815250613253565b610240516002808204905090506101c05261348a565b610300516101c0518080156157d757820490509050610340526102c051610340518080156157d7578204905090506103605261030051670de0b6b3a7640000610160518082028215828483041417156157d7579050905081818301106157d75780820190509050610340518080156157d75782049050905061036051670de0b6b3a76400008082028215828483041417156157d75790509050610260518080156157d75782049050905081818301106157d75780820190509050610380526103608051670de0b6b3a7640000610280518082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090508152506103605161038051106133875761038051610360518082106157d757808203905090506101c052613399565b610240516002808204905090506101c0525b60006103a052610240516101c051116133cb57610240516101c0518082106157d757808203905090506103a0526133e6565b6101c051610240518082106157d757808203905090506103a0525b610200516101c051655af3107a400080820490509050808210613409578161340b565b805b905090506103a051101561348a576101c051670de0b6b3a76400008082028215828483041417156157d75790509050610160518080156157d7578204905090506103c052662386f26fc0ffff6103c05111613467576000613477565b68056bc75e2d631000016103c051105b156157d75750506101c051815250613512565b8151600101808352811415612fa85750506010610220527f446964206e6f7420636f6e7665726765000000000000000000000000000000006102405261022050610220518061024001818260206001820306601f82010390500336823750506308c379a06101e0526020610200526102205160206001820306601f82010390506044016101fcfd5b565b60e051670de0b6b3a7640000808204905090506101005260e05161010051670de0b6b3a76400008082028215828483041417156157d757905090508082106157d7578082039050905061012052603b6101005111156135775760008152506137f1565b670de0b6b3a76400006101006101005110156157d7576101005160020a8080156157d75782049050905061014052610120516135b957610140518152506137f1565b670de0b6b3a7640000610160526706f05b59d3b2000061018052670de0b6b3a76400006101a05260006101c0526101e0600160ff818352015b6101e051670de0b6b3a76400008082028215828483041417156157d757905090506102005261020051670de0b6b3a76400008082106157d7578082039050905061022052610220516101205111613662576102208051610120518082106157d75780820390509050815250613686565b61012051610220518082106157d75780820390509050610220526101c051156101c0525b6101605161022051610180518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508082028215828483041417156157d75790509050610200518080156157d757820490509050610160526101c051613708576101a080516101605181818301106157d75780820190509050815250613723565b6101a08051610160518082106157d757808203905090508152505b6402540be400610160511015613769575050610140516101a0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508152506137f1565b81516001018083528114156135f257505060106101e0527f446964206e6f7420636f6e766572676500000000000000000000000000000000610200526101e0506101e0518061020001818260206001820306601f82010390500336823750506308c379a06101a05260206101c0526101e05160206001820306601f82010390506044016101bcfd5b565b6017546020604038036080396080518082028215828483041417156157d7579050905081526018546020604038036020016080396080518082028215828483041417156157d757905090506001548082028215828483041417156157d75790509050670de0b6b3a764000080820490509050816020015250565b60085460e052600654610100526fffffffffffffffffffffffffffffffff6101005116610120526101005160801c6101405260e0514210156139ce57600554610160526007546101805260e08051610180518082106157d7578082039050905081525042610180518082106157d757808203905090506101805260e051610180518082106157d757808203905090506101a0526101605160801c6101a0518082028215828483041417156157d7579050905061014051610180518082028215828483041417156157d7579050905081818301106157d7578082019050905060e0518080156157d757820490509050610140526fffffffffffffffffffffffffffffffff61016051166101a0518082028215828483041417156157d7579050905061012051610180518082028215828483041417156157d7579050905081818301106157d7578082019050905060e0518080156157d757820490509050610120525b61014051815261012051816020015250565b600b546101205260e0516101005181818301106157d757808201905090506101405261012051670de0b6b3a76400008082028215828483041417156157d7579050905061012051670de0b6b3a764000081818301106157d75780820190509050673782dace9d90000060e0518082028215828483041417156157d75790509050610140518080156157d757820490509050610100518082028215828483041417156157d75790509050610140518080156157d7578204905090508082106157d757808203905090508080156157d75782049050905061014052601154610140518082028215828483041417156157d75790509050601254670de0b6b3a7640000610140518082106157d757808203905090508082028215828483041417156157d7579050905081818301106157d75780820190509050670de0b6b3a764000080820490509050815250565b610200516002808204905090506102205261020051670de0b6b3a76400008082028215828483041417156157d7579050905060015460028082028215828483041417156157d757905090508080156157d757820490509050610240526102205160e0526102405161010052600161012052613ba761026061249b565b61026051815250565b613bbb6104e061386d565b6104e080516104a05280602001516104c05250601c546104e052601d54610500526080380360208160803960805161052052602081602001608039608051610540525061056060006002818352015b6105605115613c77576370a0823161058052306105a0526020610580602461059c6105206105605160028110156157d75760200201515afa613c51573d600060003e3d6000fd5b601f3d11156157d7576105805160016105605160028110156157d7570260170155613c8d565b4760016105605160028110156157d75702601701555b8151600101808352811415613c0a575050601e5461056052610500516104e0511115613e2c576104e051610500518082106157d757808203905090506013548082028215828483041417156157d757905090506404a817c80080820490509050610580526000610580511115613e2c576024546105a05260006105a05114613e2c5761056051670de0b6b3a76400008082028215828483041417156157d7579050905061056051610580518082106157d757808203905090508080156157d757820490509050670de0b6b3a76400008082106157d757808203905090506105c052636962f845610600526105a051610620526105c051610640526020610600604461061c6000602060a038036080396080515af1613db0573d600060003e3d6000fd5b601f3d11156157d757610600516105e0526104e080516105805160028082028215828483041417156157d757905090508082106157d757808203905090508152506104e051601c556105a0517f6059a38198b1dc42b3791087d1ff0fbd72b3179553c25f678cd246f52ffaaf596105e051610600526020610600a25b6318160ddd6105a05260206105a060046105bc602060a038036080396080515afa613e5c573d600060003e3d6000fd5b601f3d11156157d7576105a051610580526104a051610620526104c05161064052613e886105c06137f3565b6105c0805161066052806020015161068052506106205161020052610640516102205261066051610240526106805161026052613ec6610600612666565b610600516105a0526105a051601955670de0b6b3a76400006105a05161020052613ef16105c0613b2b565b6105c0518082028215828483041417156157d75790509050610580518080156157d757820490509050601e55610500516104e0511115613f33576104e051601d555b565b60025461076052600354610780526001546107a0526004546107c05260006107e052426107c051101561403f57600f5461080052426107c0518082106157d75780820390509050670de0b6b3a76400008082028215828483041417156157d75790509050610800518080156157d75782049050905060e052613fb8610840613514565b610840516108205261078051670de0b6b3a7640000610820518082106157d757808203905090508082028215828483041417156157d7579050905061076051610820518082028215828483041417156157d7579050905081818301106157d75780820190509050670de0b6b3a7640000808204905090506107605261076051600255426004555b610740516108005261074051614083576106a051610200526106c051610220526106e05161024052610700516102605261407a610820612666565b61082051610800525b6000610720511161414d576106e05161082052610700516108405261082051620f4240808204905090506108605261082080516108605181818301106157d757808201905090508152506107a051610860518082028215828483041417156157d75790509050610700516106a05160e0526106c05161010052610820516101205261084051610140526108005161016052600161018052614125610880612df5565b610880518082106157d757808203905090508080156157d75782049050905061078052614156565b61072051610780525b610780516003556318160ddd610840526020610840600461085c602060a038036080396080515afa61418d573d600060003e3d6000fd5b601f3d11156157d7576108405161082052601c5461084052601e5461086052610800516002808204905090506108805261080051670de0b6b3a76400008082028215828483041417156157d7579050905060026107a0518082028215828483041417156157d757905090508080156157d7578204905090506108a052670de0b6b3a76400006108c052670de0b6b3a76400006108e052600061086051111561436c576108805160e0526108a0516101005260016101205261424f61092061249b565b6109205161090052670de0b6b3a7640000610900518082028215828483041417156157d75790509050610820518080156157d7578204905090506108e052610840516108e0518082028215828483041417156157d75790509050610860518080156157d7578204905090506108c05260085461092052610860516108e051106142d95760006142df565b61092051155b1561435b576004610940527f4c6f7373000000000000000000000000000000000000000000000000000000006109605261094050610940518061096001818260206001820306601f82010390500336823750506308c379a0610900526020610920526109405160206001820306601f820103905060440161091cfd5b6001610920511861436c5760006008555b6108c051601c5561076051670de0b6b3a76400008082028215828483041417156157d757905090506107a0518080156157d75782049050905061090052670de0b6b3a764000061090051116143df57670de0b6b3a7640000610900518082106157d75780820390509050610900526143ff565b6109008051670de0b6b3a76400008082106157d757808203905090508152505b600d5461090051600a8082049050905080821061441c578161441e565b805b9050905061092052601f5461094052610940511561443d5760006144c3565b6108c05160026009548082028215828483041417156157d7579050905081818301106157d757808201905090506108e05160028082028215828483041417156157d75790509050670de0b6b3a76400008082106157d75780820390509050116144a75760006144c3565b6109205161090051116144bb5760006144c3565b600061086051115b156144d4576001610940526001601f555b610940511561471d576109205161090051116144f15760006144f9565b600061086051115b1561471d576107a05161090051610920518082106157d757808203905090508082028215828483041417156157d7579050905061092051610760518082028215828483041417156157d7579050905081818301106157d75780820190509050610900518080156157d7578204905090506107e0526106e05161088052610700516107e0518082028215828483041417156157d757905090506107a0518080156157d7578204905090506108a0526106a051610200526106c0516102205261088051610240526108a051610260526145d1610980612666565b6109805161096052610960516002808204905090506108805261096051670de0b6b3a76400008082028215828483041417156157d7579050905060026107e0518082028215828483041417156157d757905090508080156157d7578204905090506108a052670de0b6b3a76400006108805160e0526108a0516101005260016101205261465f61098061249b565b610980518082028215828483041417156157d75790509050610820518080156157d75782049050905061086052670de0b6b3a764000061086051116146a55760006146dc565b6108c0516002610860518082028215828483041417156157d75790509050670de0b6b3a76400008082106157d75780820390509050115b614703576000601f55610800516019556108e051601e55614741613bb0566147415661471d565b6107e0516001556109605160195561086051601e55614741565b610800516019556108e051601e556109405115614741576000601f55614741613bb0565b565b6020546157d757610a00516109e051146157d75760026109e05110156157d7576002610a005110156157d7576000610a205111156157d757614786610ac061386d565b610ac08051610a80528060200151610aa05250601754610ac052601854610ae052604036610b003760803803602081608039608051610b4052602081602001608039608051610b605250610a60516147df5760006147e5565b6109e051155b6148bc576109c0516157d7576323b872dd610b80526109a051610ba05230610bc052610a2051610be0526020610b806064610b9c6000610b406109e05160028110156157d75760200201515af1614841573d600060003e3d6000fd5b601f3d11156157d757610b8051156157d7576109e0516148ca57632e1a7d4d610b8052610a2051610ba052610b406109e05160028110156157d75760200201513b156157d757600060006024610b9c6000610b406109e05160028110156157d75760200201515af16148ca573d600060003e3d6000fd6148ca565b610a20516109c051186157d7575b610ac0610a005160028110156157d7576020020151610b8052610ac06109e05160028110156157d7576020020151610ba052610ba051610a205181818301106157d75780820190509050610ac06109e05160028110156157d7576020020152610ac06109e05160028110156157d757602002015160016109e05160028110156157d7570260170155600154610bc052610ac0516020604038036080396080518082028215828483041417156157d75790509050610ac052610ae051610bc0518082028215828483041417156157d757905090506020604038036020016080396080518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610ae052602060403803608039608051610be052602060403803602001608039608051610c005260016109e05118614a2657602060403803602001608039608051610be052602060403803608039608051610c00525b600854610c20526000610c20511115614b2357610ba08051610be0518082028215828483041417156157d7579050905081525060006109e0511115614a9657610ba051610bc0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610ba0525b610ac06109e05160028110156157d7576020020151610c4052610ba051610ac06109e05160028110156157d7576020020152610a805161020052610aa05161022052610ac05161024052610ae05161026052614af3610c60612666565b610c6051601955610c4051610ac06109e05160028110156157d7576020020152610c20514210614b235760016008555b610ac0610a005160028110156157d7576020020151610a805160e052610aa05161010052610ac05161012052610ae0516101405260195461016052610a005161018052614b71610c40612df5565b610c40518082106157d75780820390509050610b2052610ac0610a005160028110156157d757602002018051610b20518082106157d75780820390509050815250610b20805160018082106157d757808203905090508152506000610a00511115614c0d57610b2051670de0b6b3a76400008082028215828483041417156157d75790509050610bc0518080156157d757820490509050610b20525b610b208051610c00518080156157d757820490509050815250610b208051610ac05160e052610ae05161010052614c45610c406139e0565b610c4051610b20518082028215828483041417156157d757905090506402540be400808204905090508082106157d75780820390509050815250610a4051610b20511015614d04576008610c40527f536c697070616765000000000000000000000000000000000000000000000000610c6052610c4050610c405180610c6001818260206001820306601f82010390500336823750506308c379a0610c00526020610c2052610c405160206001820306601f8201039050604401610c1cfd5b610b808051610b20518082106157d75780820390509050815250610b80516001610a005160028110156157d7570260170155610a6051614d45576000614d4b565b610a0051155b614e1057610a0051614dae5763d0e30db0610c4052610b40610a005160028110156157d75760200201513b156157d757600060006004610c5c610b2051610b40610a005160028110156157d75760200201515af1614dae573d600060003e3d6000fd5b63a9059cbb610c40526109a051610c6052610b2051610c80526020610c406044610c5c6000610b40610a005160028110156157d75760200201515af1614df9573d600060003e3d6000fd5b601f3d11156157d757610c4051156157d757614e3e565b6000610c4052610c405060006000610c4051610c60610b20516109a0515af1614e3e573d600060003e3d6000fd5b610b808051610c00518082028215828483041417156157d757905090508152506000610a00511115614e9b57610b8051610bc0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610b80525b610b8051610ac0610a005160028110156157d7576020020152620186a0610a205111614ec8576000614ed2565b620186a0610b2051115b15614f9257610a2051610be0518082028215828483041417156157d75790509050610c4052610b2051610c00518082028215828483041417156157d75790509050610c60526109e05115614f5b57610c6051670de0b6b3a76400008082028215828483041417156157d75790509050610c40518080156157d757820490509050610b0052614f92565b610c4051670de0b6b3a76400008082028215828483041417156157d75790509050610c60518080156157d757820490509050610b00525b610a80516106a052610aa0516106c052610ac0516106e052610ae05161070052610b005161072052600061074052614fc8613f35565b6109a0517fb2e76ae99761dc136e598d4a629bb347eccb9532a5f8bbd72e18467c3c34cc986109e051610c4052610a2051610c6052610a0051610c8052610b2051610ca0526080610c40a2610b2051815250565b6101a05160e0526101c051610100526150366102006139e0565b6102005160028082028215828483041417156157d757905090506004808204905090506101e05260006102005261024060006002818352015b6020610240510261016001516102205261020080516102205181818301106157d75780820190509050815250815160010180835281141561506f575050610200516002808204905090506102205260006102405261028060006002818352015b6020610280510261016001516102605261022051610260511161511f57610240805161022051610260518082106157d7578082039050905081818301106157d7578082019050905081525061514e565b610240805161026051610220518082106157d7578082039050905081818301106157d757808201905090508152505b81516001018083528114156150cf5750506101e051610240518082028215828483041417156157d75790509050610200518080156157d757820490509050620186a081818301106157d75780820190509050815250565b6318160ddd610580526020610580600461059c602060a038036080396080515afa6151d5573d600060003e3d6000fd5b601f3d11156157d7576105805161056052610560516104e051116157d75760026105005110156157d757601754610580526018546105a05260006105c0526001546020604038036020016080396080518082028215828483041417156157d757905090506105e052610580516020604038036080396080518082028215828483041417156157d75790509050610600526105a0516105e0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061062052610500516152cb57670de0b6b3a76400006020604038036080396080518082028215828483041417156157d757905090506105e0525b610520516152df576019546105c052615313565b6104a051610200526104c051610220526106005161024052610620516102605261530a610640612666565b610640516105c0525b6105c051610640526106005160e05261062051610100526153356106806139e0565b61068051610660526104e051610640518082028215828483041417156157d75790509050610560518080156157d7578204905090506106805261064080516106805161066051610680518082028215828483041417156157d757905090506404a817c80080820490509050600181818301106157d757808201905090508082106157d757808203905090508082106157d757808203905090508152506104a05160e0526104c05161010052610600516101205261062051610140526106405161016052610500516101805261540b6106c0612df5565b6106c0516106a0526106006105005160028110156157d75760200201516106a0518082106157d75780820390509050670de0b6b3a76400008082028215828483041417156157d757905090506105e0518080156157d7578204905090506106c0526106a0516106006105005160028110156157d757602002015260006106e0526105405161549a5760006154b8565b620186a06106c051116154ae5760006154b8565b620186a06104e051115b1561565b57600061070052602060403803608039608051610720526001610500511861551e57610580516020604038036080396080518082028215828483041417156157d75790509050610700526020604038036020016080396080516107205261554a565b6105a0516020604038036020016080396080518082028215828483041417156157d75790509050610700525b61070051610680518082028215828483041417156157d757905090506105c0518080156157d7578204905090506107005261070051670de0b6b3a76400008082028215828483041417156157d757905090506106c051610720518082028215828483041417156157d75790509050610680516105806105005160028110156157d75760200201518082028215828483041417156157d75790509050610720518082028215828483041417156157d757905090506105c0518080156157d7578204905090508082106157d757808203905090508080156157d7578204905090506106e0526105005161565b576ec097ce7bc90715b34b9f10000000006106e0518080156157d7578204905090506106e0525b6106c05181526106e0516020820152610640516040820152606081016106005181526106205181602001525050565b60e05161569b5760008152506157d5565b60e051670de0b6b3a764000081818301106157d757808201905090506002808204905090506101005260e051610120526101406000610100818352015b6101205161010051186156f3575050610120518152506157d5565b610100516101205260e051670de0b6b3a76400008082028215828483041417156157d75790509050610100518080156157d7578204905090506101005181818301106157d757808201905090506002808204905090506101005281516001018083528114156156d85750506010610140527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101605261014050610140518061016001818260206001820306601f82010390500336823750506308c379a0610100526020610120526101405160206001820306601f820103905060440161011cfd5b565b600080fd5b6102ed615ac9036102ed6102c0396102ed615ac9036101a051816102c00152806102e0016101c05181526101e05181602001525080610320016102805181526102a0518160200152508060a0016102c0f35b600080fd000000000000000000000000babe61887f1de2713c6f97e567623453d3c79f67000000000000000000000000ecb456ea5365865ebab8a2661b0c503410e9b3470000000000000000000000000000000000000000000000000000000000061a80000000000000000000000000000000000000000000000000000083e0717e100000000000000000000000000000000000000000000000000000000000018cba800000000000000000000000000000000000000000000000000000000002aea540000000000000000000000000000000000000000000000000000001d1a94a20000000000000000000000000000000000000000000000000000000d12f0c4c6000000000000000000000000000000000000000000000000000000084c946232000000000000000000000000000000000000000000000000000000000012a05f2000000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000001716dc52ac88000000000000000000000000003a283d9c08e8b55966afb64c515f5143cf907611000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b
6020615b206080396080518060a01c615b1b5760e05260206020615b20016080396080518060a01c615b1b57610100526020610180615b20016080396080518060a01c615b1b57610120526101a0615b20016020816080396080518060a01c615b1b57610140526020602082016080396080518060a01c615b1b57610160525060e051601a5560206040615b200160803960805160801b6101805260206060615b2001608039608051610180511761018052610180516005556101805160065560206080615b2001608039608051601155602060a0615b2001608039608051601255602060c0615b2001608039608051600955602060e0615b2001608039608051600b556020610100615b2001608039608051600d556020610120615b20016080396080516013556020610160615b20016080396080516001556020610160615b20016080396080516002556020610160615b2001608039608051600355426004556020610140615b2001608039608051600f55670de0b6b3a7640000601d5542624f1a008181830110615b1b578082019050905060215561010051602455610120516101a052610140516101c052610160516101e052604e601263313ce567610200526020610200600461021c610140515afa6101e2573d600060003e3d6000fd5b601f3d1115615b1b5761020051808210615b1b57808203905090501015615b1b57601263313ce567610200526020610200600461021c610140515afa61022d573d600060003e3d6000fd5b601f3d1115615b1b5761020051808210615b1b5780820390509050600a0a61028052604e601263313ce567610240526020610240600461025c610160515afa61027b573d600060003e3d6000fd5b601f3d1115615b1b5761024051808210615b1b57808203905090501015615b1b57601263313ce567610240526020610240600461025c610160515afa6102c6573d600060003e3d6000fd5b601f3d1115615b1b5761024051808210615b1b5780820390509050600a0a6102a052615ac956600436101561000d57612499565b60046000601c37600051635b41b908811861002d576000610cc052610048565b63394747c5811861008d576084358060011c6157d757610cc0525b6000546157d7576001600055336109a052346109c052608060046109e037610cc051610a6052610079610ce0614743565b610ce051610d00526020610d006000600055f35b6365b2489b81186100db576000546157d7576001600055336109a052346109c052608060046109e0376001610a60526100c7610cc0614743565b610cc051610ce0526020610ce06000600055f35b630b4c7e4d81186100f15760006109a05261010c565b63ee22be238118610a58576064358060011c6157d7576109a0525b6000546157d75760016000556020546157d75760006004351161013457600060243511610137565b60015b156157d757610147610a0061386d565b610a0080516109c05280602001516109e0525060803803602081608039608051610a0052602081602001608039608051610a205250601754610a4052601854610a605260e036610a8037610a4051610b6052610a6051610b8052610ba060006002818352015b610a40610ba05160028110156157d75760200201516020610ba051026004013581818301106157d75780820190509050610bc052610bc051610a40610ba05160028110156157d7576020020152610bc0516001610ba05160028110156157d757026017015581516001018083528114156101ad575050610a4051610ac052610a6051610ae0526001546020604038036020016080396080518082028215828483041417156157d75790509050610ba052610a40516020604038036080396080518082028215828483041417156157d75790509050610a4052610a6051610ba0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610a6052610b60516020604038036080396080518082028215828483041417156157d75790509050610b6052610b8051610ba0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610b80526109a05161031b57346157d7575b610bc060006002818352015b6109a05161033657600061033c565b610bc051155b15610353576020610bc051026004013534186157d7575b60006020610bc051026004013511156104a4576109a0511561037c576000610bc051141561037f565b60015b15610456576323b872dd610be05233610c005230610c20526020610bc0510260040135610c40526020610be06064610bfc6000610a00610bc05160028110156157d75760200201515af16103d8573d600060003e3d6000fd5b601f3d11156157d757610be051156157d757610bc05161045657632e1a7d4d610be0526020610bc0510260040135610c0052610a00610bc05160028110156157d75760200201513b156157d757600060006024610bfc6000610a00610bc05160028110156157d75760200201515af1610456573d600060003e3d6000fd5b610a40610bc05160028110156157d7576020020151610b60610bc05160028110156157d75760200201518082106157d75780820390509050610a80610bc05160028110156157d75760200201525b8151600101808352811415610327575050600854610bc0526000610bc051116104d357601954610b4052610516565b6109c051610200526109e05161022052610b605161024052610b8051610260526104fe610be0612666565b610be051610b4052610bc05142106105165760016008555b6109c051610200526109e05161022052610a405161024052610a605161026052610541610c00612666565b610c0051610be0526318160ddd610c20526020610c206004610c3c602060a038036080396080515afa610579573d600060003e3d6000fd5b601f3d11156157d757610c2051610c00526000610b4051116105b557610be051610200526105a8610c20613b2b565b610c2051610b00526105f9565b610c0051610be0518082028215828483041417156157d75790509050610b40518080156157d757820490509050610c00518082106157d75780820390509050610b00525b6000610b005111156157d7576000610b40511161068057610be051601955670de0b6b3a7640000601e55670de0b6b3a7640000601c556340c10f19610c205233610c4052610b0051610c60526020610c206044610c3c6000602060a038036080396080515af161066e573d600060003e3d6000fd5b601f3d11156157d757610c205061097a565b610a805161016052610aa05161018052610a40516101a052610a60516101c0526106ab610c2061501c565b610c2051610b00518082028215828483041417156157d757905090506402540be40080820490509050600181818301106157d75780820190509050610b2052610b008051610b20518082106157d75780820390509050815250610c008051610b005181818301106157d757808201905090508152506340c10f19610c205233610c4052610b0051610c60526020610c206044610c3c6000602060a038036080396080515af161075f573d600060003e3d6000fd5b601f3d11156157d757610c20506000610c2052620186a0610b0051111561094257600435156107915760243515610794565b60015b1561094257606036610c4037600435156107e857610ae0516020604038036020016080396080518082028215828483041417156157d75790509050610c4052602060403803608039608051610c605261082a565b610ac0516020604038036080396080518082028215828483041417156157d75790509050610c4052602060403803602001608039608051610c60526001610c80525b610c4051610b00518082028215828483041417156157d75790509050610c00518080156157d757820490509050610c4052610c4051670de0b6b3a76400008082028215828483041417156157d757905090506020610c80510260040135610c60518082028215828483041417156157d75790509050610b0051610ac0610c805160028110156157d75760200201518082028215828483041417156157d75790509050610c60518082028215828483041417156157d75790509050610c00518080156157d7578204905090508082106157d757808203905090508080156157d757820490509050610c2052610c8051610942576ec097ce7bc90715b34b9f1000000000610c20518080156157d757820490509050610c20525b6109c0516106a0526109e0516106c052610a40516106e052610a605161070052610c205161072052610be0516107405261097a613f35565b604435610b005110156109fe576008610c20527f536c697070616765000000000000000000000000000000000000000000000000610c4052610c2050610c205180610c4001818260206001820306601f82010390500336823750506308c379a0610be0526020610c0052610c205160206001820306601f8201039050604401610bfcfd5b337f540ab385f9b5d450a27404172caade516b3ba3f4be88239ac56a2ad1de2a1f5a600435610c2052602435610c4052610b2051610c6052610c0051610c80526080610c20a2610b0051610c20526020610c206000600055f35b63fc0c546a8118610a7d57346157d757602060a0380360803960805160e052602060e0f35b63c66106578118610acc57346157d7576080380360208160803960805160e052602081602001608039608051610100525060e060043560028110156157d7576020020151610120526020610120f35b63f446c1d08118610af657346157d757610ae76101c061386d565b6101c051610200526020610200f35b63b13739298118610b2357346157d757610b116101c061386d565b6101c060200151610200526020610200f35b63ddca3f438118610b7a57346157d757610b3e6101606137f3565b61016080516101c05280602001516101e052506101c05160e0526101e05161010052610b6b6101a06139e0565b6101a051610200526020610200f35b63bb7b8b808118610c1257346157d757670de0b6b3a764000060195461020052610ba5610280613b2b565b610280518082028215828483041417156157d757905090506318160ddd6102a05260206102a060046102bc602060a038036080396080515afa610bed573d600060003e3d6000fd5b601f3d11156157d7576102a0518080156157d7578204905090506102e05260206102e0f35b63556d6e9f8118610ef257346157d757602435600435146157d757600260043510156157d757600260243510156157d7576001546020604038036020016080396080518082028215828483041417156157d757905090506104a0526017546104c0526018546104e052610c8661054061386d565b610540805161050052806020015161052052506019546105405260006008541115610d0d57610500516105c052610520516105e052610cc66105606137f3565b610560805161060052806020015161062052506105c051610200526105e0516102205261060051610240526106205161026052610d046105a0612666565b6105a051610540525b6104c060043560028110156157d75760200201805160443581818301106157d757808201905090508152506104c0516020604038036080396080518082028215828483041417156157d757905090506104c0526104e0516104a0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090506104e0526105005160e05261052051610100526104c051610120526104e05161014052610540516101605260243561018052610dc9610580612df5565b61058051610560526104c060243560028110156157d7576020020151610560518082106157d7578082039050905060018082106157d7578082039050905061058052610560516104c060243560028110156157d7576020020152600060243511610e535761058080516020604038036080396080518080156157d757820490509050815250610e8a565b61058051670de0b6b3a76400008082028215828483041417156157d757905090506104a0518080156157d757820490509050610580525b61058080516104c05160e0526104e05161010052610ea96105a06139e0565b6105a051610580518082028215828483041417156157d757905090506402540be400808204905090508082106157d75780820390509050815250610580516105a05260206105a0f35b635b36389c8118610f0757600060e052610f21565b63269b5581811861126e576064358060011c6157d75760e0525b346157d7576000546157d7576001600055608038036020816080396080516101005260208160200160803960805161012052506318160ddd610160526020610160600461017c602060a038036080396080515afa610f84573d600060003e3d6000fd5b601f3d11156157d75761016051610140526379cc67906101605233610180526004356101a0526020610160604461017c6000602060a038036080396080515af1610fd3573d600060003e3d6000fd5b601f3d11156157d75761016050601754610160526018546101805260043560018082106157d757808203905090506101a0526101c060006002818352015b6101606101c05160028110156157d75760200201516101a0518082028215828483041417156157d75790509050610140518080156157d7578204905090506101e05260206101c05102602401356101e051106157d7576101606101c05160028110156157d75760200201516101e0518082106157d7578082039050905060016101c05160028110156157d75702601701556101e0516101606101c05160028110156157d757602002015260e0516110c95760006110cf565b6101c051155b611191576101c0516111325763d0e30db0610200526101006101c05160028110156157d75760200201513b156157d75760006000600461021c6101e0516101006101c05160028110156157d75760200201515af1611132573d600060003e3d6000fd5b63a9059cbb6102005233610220526101e051610240526020610200604461021c60006101006101c05160028110156157d75760200201515af161117a573d600060003e3d6000fd5b601f3d11156157d75761020051156157d7576111bc565b6000610200526102005060006000610200516102206101e051335af16111bc573d600060003e3d6000fd5b81516001018083528114156110115750506019546101c0526101c0516101c0516101a0518082028215828483041417156157d75790509050610140518080156157d7578204905090508082106157d75780820390509050601955337fdd3c0336a16f1b64f172b7bb0dad5b2b3c7c76f91e8c4aafd6aae60dce800153610160516101e0526101805161020052610140516004358082106157d757808203905090506102205260606101e0a26000600055005b638d8ea72781186114fa57346157d7576318160ddd6104c05260206104c060046104dc602060a038036080396080515afa6112ae573d600060003e3d6000fd5b601f3d11156157d7576104c0516104a0526001546020604038036020016080396080518082028215828483041417156157d757905090506104c0526112f461052061386d565b61052080516104e052806020015161050052506113126105606137f3565b610560805161052052806020015161054052506004356020604038036080396080518082028215828483041417156157d75790509050610560526024356104c0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610580526019546105a052600060085411156113c1576104e051610200526105005161022052610520516102405261054051610260526113b86105c0612666565b6105c0516105a0525b61052080516105605181818301106157d7578082019050905081525061054080516105805181818301106157d757808201905090508152506104e051610200526105005161022052610520516102405261054051610260526114246105e0612666565b6105e0516105c0526104a0516105c0518082028215828483041417156157d757905090506105a0518080156157d7578204905090506104a0518082106157d757808203905090506105e0526105e0805161056051610160526105805161018052610520516101a052610540516101c05261149f61060061501c565b610600516105e0518082028215828483041417156157d757905090506402540be40080820490509050600181818301106157d757808201905090508082106157d757808203905090508152506105e051610600526020610600f35b634fb08c5e811861158657346157d75761151561074061386d565b61074080516108205280602001516108405250604060046108603760016108a05260006108c052610820516104a052610840516104c052610860516104e05261088051610500526108a051610520526108c051610540526115776107806151a5565b610780516108e05260206108e0f35b63f1dc3cc9811861159c5760006109a0526115b7565b638f15b6b5811861190a576064358060011c6157d7576109a0525b346157d7576000546157d75760016000556020546157d7576115da610a0061386d565b610a0080516109c05280602001516109e0525060a036610a0037600854610aa0526109c0516104a0526109e0516104c052604060046104e0376000610aa051116105205260016105405261162f610ac06151a5565b610ac08051610a00526020810151610a40526040810151610a2052606081018051610a60528060200151610a80525050604435610a005110156116e3576008610ac0527f536c697070616765000000000000000000000000000000000000000000000000610ae052610ac050610ac05180610ae001818260206001820306601f82010390500336823750506308c379a0610a80526020610aa052610ac05160206001820306601f8201039050604401610a9cfd5b610aa05142106116f35760016008555b600160243560028110156157d757026017018054610a00518082106157d757808203905090508155506379cc6790610ac05233610ae052600435610b00526020610ac06044610adc6000602060a038036080396080515af161175a573d600060003e3d6000fd5b601f3d11156157d757610ac05060803803602081608039608051610ac052602081602001608039608051610ae052506109a05161179857600061179d565b602435155b61185b576024356117fd5763d0e30db0610b0052610ac060243560028110156157d75760200201513b156157d757600060006004610b1c610a0051610ac060243560028110156157d75760200201515af16117fd573d600060003e3d6000fd5b63a9059cbb610b005233610b2052610a0051610b40526020610b006044610b1c6000610ac060243560028110156157d75760200201515af1611844573d600060003e3d6000fd5b601f3d11156157d757610b0051156157d757611886565b6000610b0052610b005060006000610b0051610b20610a0051335af1611886573d600060003e3d6000fd5b6109c0516106a0526109e0516106c052610a60516106e052610a805161070052610a405161072052610a2051610740526118be613f35565b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a060406004610b0037610a0051610b40526060610b00a2610a0051610b00526020610b006000600055f35b63c93f49e8811861193557346157d7576000546157d757600160005561192e613bb0565b6000600055005b635e2480728118611b3157346157d757601a5433186157d7576007546201517f81818301106157d757808201905090504211156157d757426201517f81818301106157d7578082019050905060443511156157d75761199561020061386d565b61020080516101c05280602001516101e052506101c05160801b610200526101e051610200511761020052610f9f60043511156157d75763ee6b280160043510156157d7576402540be3ff60243511156157d75766470de4df82000160243510156157d757670de0b6b3a76400006004358082028215828483041417156157d757905090506101c0518080156157d75782049050905061022052678ac7230489e800016102205110156157d75767016345785d89ffff6102205111156157d757670de0b6b3a76400006024358082028215828483041417156157d757905090506101e0518080156157d75782049050905061022052678ac7230489e800016102205110156157d75767016345785d89ffff6102205111156157d757610200516005554260075560043560801b61024052602435610240511761024052604435600855610240516006557fe35f0559b0642164e286b30df2077ec3a05426617a25db7578fd20ba39a6cd056101c05161026052600435610280526101e0516102a0526024356102c052426102e0526044356103005260c0610260a1005b63244c7c2e8118611bd457346157d757601a5433186157d757611b5561020061386d565b61020080516101c05280602001516101e052506101c05160801b610200526101e051610200511761020052610200516005556102005160065542600755426008557f5f0e7fba3d100c9e19446e1c92fe436f0a9a22fe99669360e4fdd6d3de2fc2846101c051610220526101e0516102405242610260526060610220a1005b63a43c33518118611d9a57346157d757601a5433186157d7576023546157d75760e0600460e0376402540be4016101005110611c165760125461010052611c25565b6207a11f6101005111156157d7575b6402540be40060e0511115611c3b5760115460e0525b6101005160e051116157d7576402540be400610120511115611c5f57601354610120525b670de0b6b3a76400006101405110611c7d57600b5461014052611c8a565b60006101405111156157d7575b670de0b6b3a7640000610160511115611ca557600954610160525b670de0b6b3a7640000610180511115611cc057600d54610180525b62093a806101a05110611cd957600f546101a052611ce6565b60006101a05111156157d7575b426203f48081818301106157d757808201905090506101c0526101c0516023556101205160165560e0516014556101005160155561014051600c5561016051600a5561018051600e556101a0516010556101c0517f913fde9a37e1f8ab67876a4d0ce80790d764fcfc5692f4529526df9c6bdde553610120516101e05260e0516102005261010051610220526101405161024052610160516102605261018051610280526101a0516102a05260e06101e0a2005b632a7dd7cd8118611eb457346157d7576000546157d7576001600055601a5433186157d75760235442106157d7576000602354146157d75760006023556016546106a0526106a05160135414611dfa57611df2613bb0565b6106a0516013555b6014546106c0526106c0516011556015546106e0526106e051601255600c546107005261070051600b55600a546107205261072051600955600e546107405261074051600d556010546107605261076051600f557f1c65bbdc939f346e5d6f0bde1f072819947438d4fc7b182cc59c2f6dc55040876106a051610780526106c0516107a0526106e0516107c052610700516107e05261072051610800526107405161082052610760516108405260e0610780a16000600055005b63226840fb8118611ed457346157d757601a5433186157d7576000602355005b636b441a408118611f58576004358060a01c6157d75760e052346157d757601a5433186157d7576022546157d757426203f48081818301106157d75780820190509050610100526101005160225560e051601b5560e051610100517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb9356000610120a3005b636a1c05ae8118611fc157346157d757601a5433186157d75760225442106157d7576000602254146157d7576000602255601b5460e05260e051601a5560e0517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c6000610100a2005b6386fbf1938118611fe157346157d757601a5433186157d7576000602255005b63e3698853811861200b57346157d757601a5433186157d7574260215411156157d7576001602055005b633046f972811861202b57346157d757601a5433186157d7576000602055005b637242e524811861205a576004358060a01c6157d75760e052346157d757601a5433186157d75760e051602455005b6354f0f7d581186120cf57346157d7576002601e548082028215828483041417156157d7579050905060025460e0526120946101a061568a565b6101a0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061018052610180516101a05260206101a0f35b63b9e8c9fd81186120eb57346157d75760015460e052602060e0f35b6386fc88d3811861210757346157d75760025460e052602060e0f35b63c146bf94811861212357346157d75760035460e052602060e0f35b636112c747811861213f57346157d75760045460e052602060e0f35b63204fe3d5811861215b57346157d75760055460e052602060e0f35b63f30cfad5811861217757346157d75760065460e052602060e0f35b63e89876ff811861219357346157d75760075460e052602060e0f35b63f9ed959781186121af57346157d75760085460e052602060e0f35b6349fe9e7781186121cb57346157d75760095460e052602060e0f35b63727ced5781186121e757346157d757600a5460e052602060e0f35b6372d4f0e2811861220357346157d757600b5460e052602060e0f35b63d7c3dcbe811861221f57346157d757600c5460e052602060e0f35b63083812e5811861223b57346157d757600d5460e052602060e0f35b634ea12c7d811861225757346157d757600e5460e052602060e0f35b63662b6274811861227357346157d757600f5460e052602060e0f35b630c5e23d4811861228f57346157d75760105460e052602060e0f35b6392526c0c81186122ab57346157d75760115460e052602060e0f35b63ee8de67581186122c757346157d75760125460e052602060e0f35b63fee3f7f981186122e357346157d75760135460e052602060e0f35b637cf9aedc81186122ff57346157d75760145460e052602060e0f35b637d1b060c811861231b57346157d75760155460e052602060e0f35b63e3824462811861233757346157d75760165460e052602060e0f35b634903b0d1811861236357346157d757600160043560028110156157d757026017015460e052602060e0f35b630f529ba2811861237f57346157d75760195460e052602060e0f35b638da5cb5b811861239b57346157d757601a5460e052602060e0f35b631ec0cdc181186123b757346157d757601b5460e052602060e0f35b637ba1a74d81186123d357346157d757601c5460e052602060e0f35b630b7b594b81186123ef57346157d757601d5460e052602060e0f35b630c46b72a811861240b57346157d757601e5460e052602060e0f35b639c868ac0811861242757346157d75760205460e052602060e0f35b632a426896811861244357346157d75760215460e052602060e0f35b63e0a0b586811861245f57346157d75760225460e052602060e0f35b63405e28f8811861247b57346157d75760235460e052602060e0f35b636e42e4d2811861249757346157d75760245460e052602060e0f35b505b005b60e051610140526101005161016052610120516124b95760006124c3565b6101605161014051105b156124d857610100516101405260e051610160525b610140516101805260006101a0526101c0600060ff818352015b610180516101e0526101805161014051610160518082028215828483041417156157d75790509050610180518080156157d75782049050905081818301106157d75780820190509050600280820490509050610180526101e0516101805111612574576101e051610180518082106157d757808203905090506101a05261258f565b610180516101e0518082106157d757808203905090506101a0525b60016101a05111156125c657610180516101a051670de0b6b3a76400008082028215828483041417156157d75790509050106125c9565b60015b156125dc57505061018051815250612664565b81516001018083528114156124f257505060106101c0527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101e0526101c0506101c051806101e001818260206001820306601f82010390500336823750506308c379a06101805260206101a0526101c05160206001820306601f820103905060440161019cfd5b565b610f9f6102005111612679576000612684565b63ee6b280161020051105b156157d7576402540be3ff610220511161269f5760006126ad565b66470de4df82000161022051105b156157d7576102405161028052610260516102a0526102a0516102805110156126e1576102605161028052610240516102a0525b633b9ac9ff61028051116126f657600061270b565b6d314dc6448d9338c15b0a0000000161028051105b156157d757655af3107a3fff6102a051670de0b6b3a76400008082028215828483041417156157d75790509050610280518080156157d75782049050905011156157d75760026102805160e0526102a051610100526000610120526127716102e061249b565b6102e0518082028215828483041417156157d757905090506102c052610280516102a05181818301106157d757808201905090506102e052610300600060ff818352015b6102c05161032052673782dace9d900000610280518082028215828483041417156157d757905090506102c0518080156157d7578204905090506102a0518082028215828483041417156157d757905090506102c0518080156157d7578204905090506103405261022051670de0b6b3a764000081818301106157d757808201905090506103605261034051610360511161287b5761034051610360518082106157d75780820390509050600181818301106157d75780820190509050610360526128a8565b61036051610340518082106157d75780820390509050600181818301106157d75780820190509050610360525b670de0b6b3a76400006102c0518082028215828483041417156157d75790509050610220518080156157d757820490509050610360518082028215828483041417156157d75790509050610220518080156157d757820490509050610360518082028215828483041417156157d757905090506127108082028215828483041417156157d75790509050610200518080156157d75782049050905061038052673782dace9d900000610340518082028215828483041417156157d75790509050610360518080156157d7578204905090506103a0526102e0516102e0516103a0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905081818301106157d757808201905090506103805160028082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090506103a0516102c0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508082106157d757808203905090506103c0526102c0516103c0516102e05181818301106157d757808201905090508082028215828483041417156157d757905090506103c0518080156157d7578204905090506103e0526102c0516102c0518082028215828483041417156157d757905090506103c0518080156157d7578204905090506104005261034051670de0b6b3a764000011612b565761040080516102c051610380516103c0518080156157d7578204905090508082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061034051670de0b6b3a76400008082106157d757808203905090508082028215828483041417156157d75790509050610340518080156157d7578204905090508082106157d75780820390509050815250612bec565b61040080516102c051610380516103c0518080156157d7578204905090508082028215828483041417156157d75790509050670de0b6b3a764000080820490509050670de0b6b3a7640000610340518082106157d757808203905090508082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090508152505b610400516103e05111612c2157610400516103e0518082106157d757808203905090506002808204905090506102c052612c3c565b6103e051610400518082106157d757808203905090506102c0525b600061042052610320516102c05111612c6e57610320516102c0518082106157d7578082039050905061042052612c89565b6102c051610320518082106157d75780820390509050610420525b662386f26fc100006102c051808210612ca25781612ca4565b805b9050905061042051655af3107a40008082028215828483041417156157d757905090501015612d6b5761046060006002818352015b6020610460510261028001516104405261044051670de0b6b3a76400008082028215828483041417156157d757905090506102c0518080156157d75782049050905061048052662386f26fc0ffff6104805111612d37576000612d47565b68056bc75e2d6310000161048051105b156157d7578151600101808352811415612cd957505050506102c051815250612df3565b81516001018083528114156127b55750506010610300527f446964206e6f7420636f6e7665726765000000000000000000000000000000006103205261030050610300518061032001818260206001820306601f82010390500336823750506308c379a06102c05260206102e0526103005160206001820306601f82010390506044016102dcfd5b565b610f9f60e05111612e07576000612e11565b63ee6b280160e051105b156157d7576402540be3ff6101005111612e2c576000612e3a565b66470de4df82000161010051105b156157d75767016345785d89ffff6101605111612e58576000612e6d565b6d314dc6448d9338c15b0a0000000161016051105b156157d7576101206001610180518082106157d7578082039050905060028110156157d75760200201516101a0527001000000000000000000000000000000006101605110156157d7576002610160510a6101a05160048082028215828483041417156157d757905090508080156157d7578204905090506101c052671bc16d674ec800006101a0518082028215828483041417156157d75790509050610160518080156157d7578204905090506101e05266470de4df81ffff6101e05111612f37576000612f47565b680ad78ebc5ac62000016101e051105b156157d7576101a051655af3107a40008082049050905061016051655af3107a400080820490509050808210612f7d5781612f7f565b805b905090506064808210612f925781612f94565b805b9050905061020052610220600060ff818352015b6101c051610240526101e0516101c0518082028215828483041417156157d7579050905060028082028215828483041417156157d75790509050610160518080156157d757820490509050610260526101a0516101c05181818301106157d757808201905090506102805261010051670de0b6b3a764000081818301106157d757808201905090506102a052610260516102a0511161307257610260516102a0518082106157d75780820390509050600181818301106157d757808201905090506102a05261309f565b6102a051610260518082106157d75780820390509050600181818301106157d757808201905090506102a0525b670de0b6b3a7640000610160518082028215828483041417156157d75790509050610100518080156157d7578204905090506102a0518082028215828483041417156157d75790509050610100518080156157d7578204905090506102a0518082028215828483041417156157d757905090506127108082028215828483041417156157d7579050905060e0518080156157d7578204905090506102c052670de0b6b3a7640000671bc16d674ec80000610260518082028215828483041417156157d757905090506102a0518080156157d75782049050905081818301106157d757808201905090506102e052670de0b6b3a76400006101c0518082028215828483041417156157d75790509050610280516102e0518082028215828483041417156157d7579050905081818301106157d757808201905090506102c05181818301106157d7578082019050905061030052610160516102e0518082028215828483041417156157d757905090506103205261032051610300511061323d576103008051610320518082106157d75780820390509050815250613253565b610240516002808204905090506101c05261348a565b610300516101c0518080156157d757820490509050610340526102c051610340518080156157d7578204905090506103605261030051670de0b6b3a7640000610160518082028215828483041417156157d7579050905081818301106157d75780820190509050610340518080156157d75782049050905061036051670de0b6b3a76400008082028215828483041417156157d75790509050610260518080156157d75782049050905081818301106157d75780820190509050610380526103608051670de0b6b3a7640000610280518082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090508152506103605161038051106133875761038051610360518082106157d757808203905090506101c052613399565b610240516002808204905090506101c0525b60006103a052610240516101c051116133cb57610240516101c0518082106157d757808203905090506103a0526133e6565b6101c051610240518082106157d757808203905090506103a0525b610200516101c051655af3107a400080820490509050808210613409578161340b565b805b905090506103a051101561348a576101c051670de0b6b3a76400008082028215828483041417156157d75790509050610160518080156157d7578204905090506103c052662386f26fc0ffff6103c05111613467576000613477565b68056bc75e2d631000016103c051105b156157d75750506101c051815250613512565b8151600101808352811415612fa85750506010610220527f446964206e6f7420636f6e7665726765000000000000000000000000000000006102405261022050610220518061024001818260206001820306601f82010390500336823750506308c379a06101e0526020610200526102205160206001820306601f82010390506044016101fcfd5b565b60e051670de0b6b3a7640000808204905090506101005260e05161010051670de0b6b3a76400008082028215828483041417156157d757905090508082106157d7578082039050905061012052603b6101005111156135775760008152506137f1565b670de0b6b3a76400006101006101005110156157d7576101005160020a8080156157d75782049050905061014052610120516135b957610140518152506137f1565b670de0b6b3a7640000610160526706f05b59d3b2000061018052670de0b6b3a76400006101a05260006101c0526101e0600160ff818352015b6101e051670de0b6b3a76400008082028215828483041417156157d757905090506102005261020051670de0b6b3a76400008082106157d7578082039050905061022052610220516101205111613662576102208051610120518082106157d75780820390509050815250613686565b61012051610220518082106157d75780820390509050610220526101c051156101c0525b6101605161022051610180518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508082028215828483041417156157d75790509050610200518080156157d757820490509050610160526101c051613708576101a080516101605181818301106157d75780820190509050815250613723565b6101a08051610160518082106157d757808203905090508152505b6402540be400610160511015613769575050610140516101a0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508152506137f1565b81516001018083528114156135f257505060106101e0527f446964206e6f7420636f6e766572676500000000000000000000000000000000610200526101e0506101e0518061020001818260206001820306601f82010390500336823750506308c379a06101a05260206101c0526101e05160206001820306601f82010390506044016101bcfd5b565b6017546020604038036080396080518082028215828483041417156157d7579050905081526018546020604038036020016080396080518082028215828483041417156157d757905090506001548082028215828483041417156157d75790509050670de0b6b3a764000080820490509050816020015250565b60085460e052600654610100526fffffffffffffffffffffffffffffffff6101005116610120526101005160801c6101405260e0514210156139ce57600554610160526007546101805260e08051610180518082106157d7578082039050905081525042610180518082106157d757808203905090506101805260e051610180518082106157d757808203905090506101a0526101605160801c6101a0518082028215828483041417156157d7579050905061014051610180518082028215828483041417156157d7579050905081818301106157d7578082019050905060e0518080156157d757820490509050610140526fffffffffffffffffffffffffffffffff61016051166101a0518082028215828483041417156157d7579050905061012051610180518082028215828483041417156157d7579050905081818301106157d7578082019050905060e0518080156157d757820490509050610120525b61014051815261012051816020015250565b600b546101205260e0516101005181818301106157d757808201905090506101405261012051670de0b6b3a76400008082028215828483041417156157d7579050905061012051670de0b6b3a764000081818301106157d75780820190509050673782dace9d90000060e0518082028215828483041417156157d75790509050610140518080156157d757820490509050610100518082028215828483041417156157d75790509050610140518080156157d7578204905090508082106157d757808203905090508080156157d75782049050905061014052601154610140518082028215828483041417156157d75790509050601254670de0b6b3a7640000610140518082106157d757808203905090508082028215828483041417156157d7579050905081818301106157d75780820190509050670de0b6b3a764000080820490509050815250565b610200516002808204905090506102205261020051670de0b6b3a76400008082028215828483041417156157d7579050905060015460028082028215828483041417156157d757905090508080156157d757820490509050610240526102205160e0526102405161010052600161012052613ba761026061249b565b61026051815250565b613bbb6104e061386d565b6104e080516104a05280602001516104c05250601c546104e052601d54610500526080380360208160803960805161052052602081602001608039608051610540525061056060006002818352015b6105605115613c77576370a0823161058052306105a0526020610580602461059c6105206105605160028110156157d75760200201515afa613c51573d600060003e3d6000fd5b601f3d11156157d7576105805160016105605160028110156157d7570260170155613c8d565b4760016105605160028110156157d75702601701555b8151600101808352811415613c0a575050601e5461056052610500516104e0511115613e2c576104e051610500518082106157d757808203905090506013548082028215828483041417156157d757905090506404a817c80080820490509050610580526000610580511115613e2c576024546105a05260006105a05114613e2c5761056051670de0b6b3a76400008082028215828483041417156157d7579050905061056051610580518082106157d757808203905090508080156157d757820490509050670de0b6b3a76400008082106157d757808203905090506105c052636962f845610600526105a051610620526105c051610640526020610600604461061c6000602060a038036080396080515af1613db0573d600060003e3d6000fd5b601f3d11156157d757610600516105e0526104e080516105805160028082028215828483041417156157d757905090508082106157d757808203905090508152506104e051601c556105a0517f6059a38198b1dc42b3791087d1ff0fbd72b3179553c25f678cd246f52ffaaf596105e051610600526020610600a25b6318160ddd6105a05260206105a060046105bc602060a038036080396080515afa613e5c573d600060003e3d6000fd5b601f3d11156157d7576105a051610580526104a051610620526104c05161064052613e886105c06137f3565b6105c0805161066052806020015161068052506106205161020052610640516102205261066051610240526106805161026052613ec6610600612666565b610600516105a0526105a051601955670de0b6b3a76400006105a05161020052613ef16105c0613b2b565b6105c0518082028215828483041417156157d75790509050610580518080156157d757820490509050601e55610500516104e0511115613f33576104e051601d555b565b60025461076052600354610780526001546107a0526004546107c05260006107e052426107c051101561403f57600f5461080052426107c0518082106157d75780820390509050670de0b6b3a76400008082028215828483041417156157d75790509050610800518080156157d75782049050905060e052613fb8610840613514565b610840516108205261078051670de0b6b3a7640000610820518082106157d757808203905090508082028215828483041417156157d7579050905061076051610820518082028215828483041417156157d7579050905081818301106157d75780820190509050670de0b6b3a7640000808204905090506107605261076051600255426004555b610740516108005261074051614083576106a051610200526106c051610220526106e05161024052610700516102605261407a610820612666565b61082051610800525b6000610720511161414d576106e05161082052610700516108405261082051620f4240808204905090506108605261082080516108605181818301106157d757808201905090508152506107a051610860518082028215828483041417156157d75790509050610700516106a05160e0526106c05161010052610820516101205261084051610140526108005161016052600161018052614125610880612df5565b610880518082106157d757808203905090508080156157d75782049050905061078052614156565b61072051610780525b610780516003556318160ddd610840526020610840600461085c602060a038036080396080515afa61418d573d600060003e3d6000fd5b601f3d11156157d7576108405161082052601c5461084052601e5461086052610800516002808204905090506108805261080051670de0b6b3a76400008082028215828483041417156157d7579050905060026107a0518082028215828483041417156157d757905090508080156157d7578204905090506108a052670de0b6b3a76400006108c052670de0b6b3a76400006108e052600061086051111561436c576108805160e0526108a0516101005260016101205261424f61092061249b565b6109205161090052670de0b6b3a7640000610900518082028215828483041417156157d75790509050610820518080156157d7578204905090506108e052610840516108e0518082028215828483041417156157d75790509050610860518080156157d7578204905090506108c05260085461092052610860516108e051106142d95760006142df565b61092051155b1561435b576004610940527f4c6f7373000000000000000000000000000000000000000000000000000000006109605261094050610940518061096001818260206001820306601f82010390500336823750506308c379a0610900526020610920526109405160206001820306601f820103905060440161091cfd5b6001610920511861436c5760006008555b6108c051601c5561076051670de0b6b3a76400008082028215828483041417156157d757905090506107a0518080156157d75782049050905061090052670de0b6b3a764000061090051116143df57670de0b6b3a7640000610900518082106157d75780820390509050610900526143ff565b6109008051670de0b6b3a76400008082106157d757808203905090508152505b600d5461090051600a8082049050905080821061441c578161441e565b805b9050905061092052601f5461094052610940511561443d5760006144c3565b6108c05160026009548082028215828483041417156157d7579050905081818301106157d757808201905090506108e05160028082028215828483041417156157d75790509050670de0b6b3a76400008082106157d75780820390509050116144a75760006144c3565b6109205161090051116144bb5760006144c3565b600061086051115b156144d4576001610940526001601f555b610940511561471d576109205161090051116144f15760006144f9565b600061086051115b1561471d576107a05161090051610920518082106157d757808203905090508082028215828483041417156157d7579050905061092051610760518082028215828483041417156157d7579050905081818301106157d75780820190509050610900518080156157d7578204905090506107e0526106e05161088052610700516107e0518082028215828483041417156157d757905090506107a0518080156157d7578204905090506108a0526106a051610200526106c0516102205261088051610240526108a051610260526145d1610980612666565b6109805161096052610960516002808204905090506108805261096051670de0b6b3a76400008082028215828483041417156157d7579050905060026107e0518082028215828483041417156157d757905090508080156157d7578204905090506108a052670de0b6b3a76400006108805160e0526108a0516101005260016101205261465f61098061249b565b610980518082028215828483041417156157d75790509050610820518080156157d75782049050905061086052670de0b6b3a764000061086051116146a55760006146dc565b6108c0516002610860518082028215828483041417156157d75790509050670de0b6b3a76400008082106157d75780820390509050115b614703576000601f55610800516019556108e051601e55614741613bb0566147415661471d565b6107e0516001556109605160195561086051601e55614741565b610800516019556108e051601e556109405115614741576000601f55614741613bb0565b565b6020546157d757610a00516109e051146157d75760026109e05110156157d7576002610a005110156157d7576000610a205111156157d757614786610ac061386d565b610ac08051610a80528060200151610aa05250601754610ac052601854610ae052604036610b003760803803602081608039608051610b4052602081602001608039608051610b605250610a60516147df5760006147e5565b6109e051155b6148bc576109c0516157d7576323b872dd610b80526109a051610ba05230610bc052610a2051610be0526020610b806064610b9c6000610b406109e05160028110156157d75760200201515af1614841573d600060003e3d6000fd5b601f3d11156157d757610b8051156157d7576109e0516148ca57632e1a7d4d610b8052610a2051610ba052610b406109e05160028110156157d75760200201513b156157d757600060006024610b9c6000610b406109e05160028110156157d75760200201515af16148ca573d600060003e3d6000fd6148ca565b610a20516109c051186157d7575b610ac0610a005160028110156157d7576020020151610b8052610ac06109e05160028110156157d7576020020151610ba052610ba051610a205181818301106157d75780820190509050610ac06109e05160028110156157d7576020020152610ac06109e05160028110156157d757602002015160016109e05160028110156157d7570260170155600154610bc052610ac0516020604038036080396080518082028215828483041417156157d75790509050610ac052610ae051610bc0518082028215828483041417156157d757905090506020604038036020016080396080518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610ae052602060403803608039608051610be052602060403803602001608039608051610c005260016109e05118614a2657602060403803602001608039608051610be052602060403803608039608051610c00525b600854610c20526000610c20511115614b2357610ba08051610be0518082028215828483041417156157d7579050905081525060006109e0511115614a9657610ba051610bc0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610ba0525b610ac06109e05160028110156157d7576020020151610c4052610ba051610ac06109e05160028110156157d7576020020152610a805161020052610aa05161022052610ac05161024052610ae05161026052614af3610c60612666565b610c6051601955610c4051610ac06109e05160028110156157d7576020020152610c20514210614b235760016008555b610ac0610a005160028110156157d7576020020151610a805160e052610aa05161010052610ac05161012052610ae0516101405260195461016052610a005161018052614b71610c40612df5565b610c40518082106157d75780820390509050610b2052610ac0610a005160028110156157d757602002018051610b20518082106157d75780820390509050815250610b20805160018082106157d757808203905090508152506000610a00511115614c0d57610b2051670de0b6b3a76400008082028215828483041417156157d75790509050610bc0518080156157d757820490509050610b20525b610b208051610c00518080156157d757820490509050815250610b208051610ac05160e052610ae05161010052614c45610c406139e0565b610c4051610b20518082028215828483041417156157d757905090506402540be400808204905090508082106157d75780820390509050815250610a4051610b20511015614d04576008610c40527f536c697070616765000000000000000000000000000000000000000000000000610c6052610c4050610c405180610c6001818260206001820306601f82010390500336823750506308c379a0610c00526020610c2052610c405160206001820306601f8201039050604401610c1cfd5b610b808051610b20518082106157d75780820390509050815250610b80516001610a005160028110156157d7570260170155610a6051614d45576000614d4b565b610a0051155b614e1057610a0051614dae5763d0e30db0610c4052610b40610a005160028110156157d75760200201513b156157d757600060006004610c5c610b2051610b40610a005160028110156157d75760200201515af1614dae573d600060003e3d6000fd5b63a9059cbb610c40526109a051610c6052610b2051610c80526020610c406044610c5c6000610b40610a005160028110156157d75760200201515af1614df9573d600060003e3d6000fd5b601f3d11156157d757610c4051156157d757614e3e565b6000610c4052610c405060006000610c4051610c60610b20516109a0515af1614e3e573d600060003e3d6000fd5b610b808051610c00518082028215828483041417156157d757905090508152506000610a00511115614e9b57610b8051610bc0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610b80525b610b8051610ac0610a005160028110156157d7576020020152620186a0610a205111614ec8576000614ed2565b620186a0610b2051115b15614f9257610a2051610be0518082028215828483041417156157d75790509050610c4052610b2051610c00518082028215828483041417156157d75790509050610c60526109e05115614f5b57610c6051670de0b6b3a76400008082028215828483041417156157d75790509050610c40518080156157d757820490509050610b0052614f92565b610c4051670de0b6b3a76400008082028215828483041417156157d75790509050610c60518080156157d757820490509050610b00525b610a80516106a052610aa0516106c052610ac0516106e052610ae05161070052610b005161072052600061074052614fc8613f35565b6109a0517fb2e76ae99761dc136e598d4a629bb347eccb9532a5f8bbd72e18467c3c34cc986109e051610c4052610a2051610c6052610a0051610c8052610b2051610ca0526080610c40a2610b2051815250565b6101a05160e0526101c051610100526150366102006139e0565b6102005160028082028215828483041417156157d757905090506004808204905090506101e05260006102005261024060006002818352015b6020610240510261016001516102205261020080516102205181818301106157d75780820190509050815250815160010180835281141561506f575050610200516002808204905090506102205260006102405261028060006002818352015b6020610280510261016001516102605261022051610260511161511f57610240805161022051610260518082106157d7578082039050905081818301106157d7578082019050905081525061514e565b610240805161026051610220518082106157d7578082039050905081818301106157d757808201905090508152505b81516001018083528114156150cf5750506101e051610240518082028215828483041417156157d75790509050610200518080156157d757820490509050620186a081818301106157d75780820190509050815250565b6318160ddd610580526020610580600461059c602060a038036080396080515afa6151d5573d600060003e3d6000fd5b601f3d11156157d7576105805161056052610560516104e051116157d75760026105005110156157d757601754610580526018546105a05260006105c0526001546020604038036020016080396080518082028215828483041417156157d757905090506105e052610580516020604038036080396080518082028215828483041417156157d75790509050610600526105a0516105e0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061062052610500516152cb57670de0b6b3a76400006020604038036080396080518082028215828483041417156157d757905090506105e0525b610520516152df576019546105c052615313565b6104a051610200526104c051610220526106005161024052610620516102605261530a610640612666565b610640516105c0525b6105c051610640526106005160e05261062051610100526153356106806139e0565b61068051610660526104e051610640518082028215828483041417156157d75790509050610560518080156157d7578204905090506106805261064080516106805161066051610680518082028215828483041417156157d757905090506404a817c80080820490509050600181818301106157d757808201905090508082106157d757808203905090508082106157d757808203905090508152506104a05160e0526104c05161010052610600516101205261062051610140526106405161016052610500516101805261540b6106c0612df5565b6106c0516106a0526106006105005160028110156157d75760200201516106a0518082106157d75780820390509050670de0b6b3a76400008082028215828483041417156157d757905090506105e0518080156157d7578204905090506106c0526106a0516106006105005160028110156157d757602002015260006106e0526105405161549a5760006154b8565b620186a06106c051116154ae5760006154b8565b620186a06104e051115b1561565b57600061070052602060403803608039608051610720526001610500511861551e57610580516020604038036080396080518082028215828483041417156157d75790509050610700526020604038036020016080396080516107205261554a565b6105a0516020604038036020016080396080518082028215828483041417156157d75790509050610700525b61070051610680518082028215828483041417156157d757905090506105c0518080156157d7578204905090506107005261070051670de0b6b3a76400008082028215828483041417156157d757905090506106c051610720518082028215828483041417156157d75790509050610680516105806105005160028110156157d75760200201518082028215828483041417156157d75790509050610720518082028215828483041417156157d757905090506105c0518080156157d7578204905090508082106157d757808203905090508080156157d7578204905090506106e0526105005161565b576ec097ce7bc90715b34b9f10000000006106e0518080156157d7578204905090506106e0525b6106c05181526106e0516020820152610640516040820152606081016106005181526106205181602001525050565b60e05161569b5760008152506157d5565b60e051670de0b6b3a764000081818301106157d757808201905090506002808204905090506101005260e051610120526101406000610100818352015b6101205161010051186156f3575050610120518152506157d5565b610100516101205260e051670de0b6b3a76400008082028215828483041417156157d75790509050610100518080156157d7578204905090506101005181818301106157d757808201905090506002808204905090506101005281516001018083528114156156d85750506010610140527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101605261014050610140518061016001818260206001820306601f82010390500336823750506308c379a0610100526020610120526101405160206001820306601f820103905060440161011cfd5b565b600080fd5b6102ed615ac9036102ed6102c0396102ed615ac9036101a051816102c00152806102e0016101c05181526101e05181602001525080610320016102805181526102a0518160200152508060a0016102c0f35b600080fd000000000000000000000000babe61887f1de2713c6f97e567623453d3c79f67000000000000000000000000ecb456ea5365865ebab8a2661b0c503410e9b3470000000000000000000000000000000000000000000000000000000000061a80000000000000000000000000000000000000000000000000000083e0717e100000000000000000000000000000000000000000000000000000000000018cba800000000000000000000000000000000000000000000000000000000002aea540000000000000000000000000000000000000000000000000000001d1a94a20000000000000000000000000000000000000000000000000000000d12f0c4c6000000000000000000000000000000000000000000000000000000084c946232000000000000000000000000000000000000000000000000000000000012a05f2000000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000001716dc52ac88000000000000000000000000003a283d9c08e8b55966afb64c515f5143cf907611000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b