xDAI Price: $0.999887 (-0.02%)
Gas: 1 GWei

Contract

0x056C6C5e684CeC248635eD86033378Cc444459B0
Transaction Hash
Method
Block
From
To
Remove_liquidity...393625642025-04-03 3:44:4020 days ago1743651880IN
0x056C6C5e...c444459B0
0 xDAI0.000336471.2
Remove_liquidity...377912932024-12-30 17:05:30113 days ago1735578330IN
0x056C6C5e...c444459B0
0 xDAI0.000300741.1
Remove_liquidity376447342024-12-21 20:49:50122 days ago1734814190IN
0x056C6C5e...c444459B0
0 xDAI0.000133511
Add_liquidity369080142024-11-07 21:42:35166 days ago1731015755IN
0x056C6C5e...c444459B0
0 xDAI0.00025281.00000001
Remove_liquidity369079752024-11-07 21:39:05166 days ago1731015545IN
0x056C6C5e...c444459B0
0 xDAI0.000228451.47
Add_liquidity363605742024-10-06 3:55:40199 days ago1728186940IN
0x056C6C5e...c444459B0
0 xDAI0.000636652.1
Add_liquidity356996412024-08-27 19:44:15238 days ago1724787855IN
0x056C6C5e...c444459B0
0 xDAI0.000295821
Exchange356749982024-08-26 8:29:05240 days ago1724660945IN
0x056C6C5e...c444459B0
0 xDAI0.000982653.03
Exchange356739662024-08-26 7:00:40240 days ago1724655640IN
0x056C6C5e...c444459B0
0 xDAI0.000307281
Exchange356734502024-08-26 6:16:20240 days ago1724652980IN
0x056C6C5e...c444459B0
0 xDAI0.000329621
Add_liquidity355642662024-08-19 16:58:55246 days ago1724086735IN
0x056C6C5e...c444459B0
0 xDAI0.000340621
Claim_admin_fees354508282024-08-12 19:32:55253 days ago1723491175IN
0x056C6C5e...c444459B0
0 xDAI0.000138811.455
Claim_admin_fees354434112024-08-12 8:52:55254 days ago1723452775IN
0x056C6C5e...c444459B0
0 xDAI0.000281282
Remove_liquidity...346985082024-06-28 18:40:50298 days ago1719600050IN
0x056C6C5e...c444459B0
0 xDAI0.000926653.1
Claim_admin_fees346349062024-06-24 23:05:40302 days ago1719270340IN
0x056C6C5e...c444459B0
0 xDAI0.000305953
Remove_liquidity339813092024-05-16 22:48:40341 days ago1715899720IN
0x056C6C5e...c444459B0
0 xDAI0.000163771.00000001
Remove_liquidity337373852024-05-02 9:37:00356 days ago1714642620IN
0x056C6C5e...c444459B0
0 xDAI0.000163741.00000001
Remove_liquidity337264512024-05-01 17:50:05356 days ago1714585805IN
0x056C6C5e...c444459B0
0 xDAI0.000163741.00000002
Remove_liquidity...336231152024-04-25 13:20:05363 days ago1714051205IN
0x056C6C5e...c444459B0
0 xDAI0.000471491.6
Add_liquidity332601172024-04-03 17:56:05384 days ago1712166965IN
0x056C6C5e...c444459B0
0 xDAI0.000345631.00000599
Add_liquidity332597142024-04-03 17:20:30384 days ago1712164830IN
0x056C6C5e...c444459B0
0 xDAI0.000335711.00000003
Add_liquidity331521092024-03-28 4:58:00391 days ago1711601880IN
0x056C6C5e...c444459B0
0 xDAI0.000300741
Remove_liquidity330458952024-03-21 18:28:20397 days ago1711045700IN
0x056C6C5e...c444459B0
0 xDAI0.000163741.00000001
Remove_liquidity330412972024-03-21 11:47:55398 days ago1711021675IN
0x056C6C5e...c444459B0
0 xDAI0.000163771.00000024
Remove_liquidity328151172024-03-07 19:42:55411 days ago1709840575IN
0x056C6C5e...c444459B0
0 xDAI0.000425452.9
View all transactions

View more zero value Internal Transactions in Advanced View mode

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Vyper_contract

Compiler Version
vyper:0.3.3

Optimization Enabled:
N/A

Other Settings:
default evmVersion, None license

Contract Source Code (Vyper language format)

# @version 0.3.3
# (c) Curve.Fi, 2022
# 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
 
 
# 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(uint256) = 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: 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
 
 
@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())]
 
 
### 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 = unsafe_div(D + x[0] * x[1] / D, N_COINS)
        if D > D_prev:
            diff = unsafe_sub(D, D_prev)
        else:
            diff = unsafe_sub(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]
    __g1k0: uint256 = gamma + 10**18
 
    for i in range(255):
        D_prev: uint256 = D
        assert D > 0
        # Unsafe ivision by D is now safe
 
        # K0: uint256 = 10**18
        # for _x in x:
        #     K0 = K0 * _x * N_COINS / D
        # collapsed for 2 coins
        K0: uint256 = unsafe_div(unsafe_div((10**18 * N_COINS**2) * x[0], D) * x[1], D)
 
        _g1k0: uint256 = __g1k0
        if _g1k0 > K0:
            _g1k0 = unsafe_sub(_g1k0, K0) + 1  # > 0
        else:
            _g1k0 = unsafe_sub(K0, _g1k0) + 1  # > 0
 
        # D / (A * N**N) * _g1k0**2 / gamma**2
        mul1: uint256 = unsafe_div(unsafe_div(unsafe_div(10**18 * D, gamma) * _g1k0, gamma) * _g1k0 * A_MULTIPLIER, ANN)
 
        # 2*N*K0 / _g1k0
        mul2: uint256 = unsafe_div(((2 * 10**18) * N_COINS) * K0, _g1k0)
 
        neg_fprime: uint256 = (S + unsafe_div(S * mul2, 10**18)) + mul1 * N_COINS / K0 - unsafe_div(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 += unsafe_div(D * (mul1 / neg_fprime), 10**18) * unsafe_sub(10**18, K0) / K0
        else:
            D_minus -= unsafe_div(D * (mul1 / neg_fprime), 10**18) * unsafe_sub(K0, 10**18) / K0
 
        if D_plus > D_minus:
            D = unsafe_sub(D_plus, D_minus)
        else:
            D = unsafe_div(unsafe_sub(D_minus, D_plus), 2)
 
        diff: uint256 = 0
        if D > D_prev:
            diff = unsafe_sub(D, D_prev)
        else:
            diff = unsafe_sub(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)
 
    __g1k0: uint256 = gamma + 10**18
 
    for j in range(255):
        y_prev: uint256 = y
 
        K0: uint256 = unsafe_div(K0_i * y * N_COINS, D)
        S: uint256 = x_j + y
 
        _g1k0: uint256 = __g1k0
        if _g1k0 > K0:
            _g1k0 = unsafe_sub(_g1k0, K0) + 1
        else:
            _g1k0 = unsafe_sub(K0, _g1k0) + 1
 
        # D / (A * N**N) * _g1k0**2 / gamma**2
        mul1: uint256 = unsafe_div(unsafe_div(unsafe_div(10**18 * D, gamma) * _g1k0, gamma) * _g1k0 * A_MULTIPLIER, ANN)
 
        # 2*K0 / _g1k0
        mul2: uint256 = unsafe_div(10**18 + (2 * 10**18) * K0, _g1k0)
 
        yfprime: uint256 = 10**18 * y + S * mul2 + mul1
        _dyfprime: uint256 = D * mul2
        if yfprime < _dyfprime:
            y = unsafe_div(y_prev, 2)
            continue
        else:
            yfprime = unsafe_sub(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 = unsafe_div(y_prev, 2)
        else:
            y = unsafe_sub(y_plus, y_minus)
 
        diff: uint256 = 0
        if y > y_prev:
            diff = unsafe_sub(y, y_prev)
        else:
            diff = unsafe_sub(y_prev, y)
        if diff < max(convergence_limit, unsafe_div(y, 10**14)):
            frac: uint256 = unsafe_div(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 = unsafe_div(power, 10**18)
    if intpow > 59:
        return 0
    otherpow: uint256 = unsafe_sub(power, unsafe_mul(intpow, 10**18))  # < 10**18
    # result: uint256 = unsafe_div(10**18, pow_mod256(2, intpow))
    result: uint256 = pow_mod256(2, intpow)
    result = unsafe_div(10**18, result)
    if otherpow == 0:
        return result
 
    term: uint256 = 10**18
    S: uint256 = 10**18
    neg: bool = False
 
    for i in range(1, 256):
        K: uint256 = unsafe_mul(i, 10**18)  # <= 255 * 10**18; >= 10**18
        c: uint256 = unsafe_sub(K, 10**18)  # <= 254 * 10**18; < K
        if otherpow > c:  # c < otherpow < 10**18 <= K -> c < K
            c = unsafe_sub(otherpow, c)
            neg = not neg
        else:
            c = unsafe_sub(c, otherpow)  # c < K
        # c <= 254 * 10**18, < K -> (c/2) / K < 1 -> term * c/2 / K <= 10**18
        term = unsafe_div(unsafe_mul(term, unsafe_div(c, 2)), K)
        if neg:
            S -= term
        else:
            S += term
        if term < EXP_PRECISION:
            return unsafe_div(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],
            unsafe_div(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 = unsafe_mul(fee_gamma, 10**18) / (
        unsafe_add(fee_gamma, 10**18) - unsafe_div((10**18 * N_COINS**N_COINS) * xp[0] / f * xp[1], f)
    )
    return unsafe_div(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] = [unsafe_div(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):
        self.balances[i] = ERC20(_coins[i]).balanceOf(self)
 
    vprice: uint256 = self.virtual_price
 
    if xcp_profit > xcp_profit_a:
        fees: uint256 = unsafe_div((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 -= unsafe_mul(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
@view
def internal_price_oracle() -> uint256:
    price_oracle: uint256 = self._price_oracle
    last_prices_timestamp: uint256 = self.last_prices_timestamp
 
    if last_prices_timestamp < block.timestamp:
        ma_half_time: uint256 = self.ma_half_time
        last_prices: uint256 = self.last_prices
        alpha: uint256 = self.halfpow(unsafe_div(unsafe_mul(block.timestamp - last_prices_timestamp, 10**18), ma_half_time))
        return unsafe_div(last_prices * (10**18 - alpha) + price_oracle * alpha, 10**18)
 
    else:
        return price_oracle
 
 
@external
@view
def price_oracle() -> uint256:
    return self.internal_price_oracle()
 
 
@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(unsafe_div(unsafe_mul(block.timestamp - last_prices_timestamp, 10**18), ma_half_time))
        price_oracle = unsafe_div(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 = unsafe_div(__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] = [unsafe_div(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 = unsafe_sub(norm, 10**18)
    else:
        norm = unsafe_sub(10**18, norm)
    adjustment_step: uint256 = max(self.adjustment_step, unsafe_div(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 + unsafe_mul(self.allowed_extra_profit, 2)) 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 = unsafe_div(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 = [unsafe_div(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, i: uint256, j: uint256, dx: uint256, min_dy: uint256,
              receiver: address, callbacker: address, callback_sig: Bytes[4]) -> 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
 
    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
 
    # Transfer input and output at the same time
    if callback_sig == b"\x00\x00\x00\x00":
        assert ERC20(_coins[i]).transferFrom(sender, self, dx)
    else:
        c: address = _coins[i]
        b: uint256 = ERC20(c).balanceOf(self)
        raw_call(callbacker,
                 concat(
                    callback_sig,
                    convert(sender, bytes32),
                    convert(receiver, bytes32),
                    convert(c, bytes32),
                    convert(dx, bytes32),
                    convert(dy, bytes32)
                 )
        )
        assert ERC20(c).balanceOf(self) - b == dx  # dev: callback didn't give us coins
 
    assert ERC20(_coins[j]).transfer(receiver, 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
 
 
@external
@nonreentrant('lock')
def exchange(i: uint256, j: uint256, dx: uint256, min_dy: uint256,
             receiver: address = msg.sender) -> uint256:
    """
    Exchange using WETH by default
    """
    return self._exchange(msg.sender, i, j, dx, min_dy, receiver, ZERO_ADDRESS, b'\x00\x00\x00\x00')
 
 
@external
@nonreentrant('lock')
def exchange_extended(i: uint256, j: uint256, dx: uint256, min_dy: uint256,
                      sender: address, receiver: address, cb: Bytes[4]) -> uint256:
    assert cb != b'\x00\x00\x00\x00'  # dev: No callback specified
    return self._exchange(sender, i, j, dx, min_dy, receiver, msg.sender, cb)
 
 
@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
 
 
@external
@nonreentrant('lock')
def add_liquidity(amounts: uint256[N_COINS], min_mint_amount: uint256, receiver: address = msg.sender) -> 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]
 
    for i in range(N_COINS):
        if amounts[i] > 0:
            assert ERC20(_coins[i]).transferFrom(msg.sender, self, amounts[i])
            amountsp[i] = xp[i] - xp_old[i]
    assert amounts[0] > 0 or amounts[1] > 0  # dev: no coins to add
 
    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(receiver, 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(receiver, d_token)
 
    assert d_token >= min_mint_amount, "Slippage"
 
    log AddLiquidity(receiver, amounts, d_token_fee, token_supply)
 
    return d_token
 
 
@external
@nonreentrant('lock')
def remove_liquidity(_amount: uint256, min_amounts: uint256[N_COINS], receiver: address = msg.sender):
    """
    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
        assert ERC20(_coins[i]).transfer(receiver, 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, receiver: address = msg.sender) -> 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
    assert ERC20(_coins[i]).transfer(receiver, 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
    """
    return 2 * self.virtual_price * self.sqrt_int(self.internal_price_oracle()) / 10**18

Contract Security Audit

Contract ABI

API
[{"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":"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":"view","type":"function","name":"price_oracle","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","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":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"},{"name":"receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"exchange_extended","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"},{"name":"sender","type":"address"},{"name":"receiver","type":"address"},{"name":"cb","type":"bytes"}],"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":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"amounts","type":"uint256[2]"},{"name":"min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"amounts","type":"uint256[2]"},{"name":"min_mint_amount","type":"uint256"},{"name":"receiver","type":"address"}],"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":"receiver","type":"address"}],"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":"receiver","type":"address"}],"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":"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"}]}]

60206154126000396000518060a01c61540d5760405260206154326000396000518060a01c61540d5760605260206155926000396000518060a01c61540d5760805260206155b26000396000518060a01c61540d5760a05260206155d26000396000518060a01c61540d5760c052604051601a55602061545260003960005160801b60e052602061547260003960005160e0511760e05260e05160055560e051600655602061549260003960005160115560206154b260003960005160125560206154d260003960005160095560206154f2600039600051600b556020615512600039600051600d556020615532600039600051601355602061557260003960005160015560206155726000396000516002556020615572600039600051600355426004556020615552600039600051600f55670de0b6b3a7640000601d5542624f1a00818183011061540d5780820190509050602155606051602455608051630000514e5260a051630000516e5260c051630000518e52604e601263313ce567610100526020610100600461011c60a0515afa6101a2573d600060003e3d6000fd5b60203d1061540d576101005180821061540d5780820390509050101561540d57601263313ce567610100526020610100600461011c60a0515afa6101eb573d600060003e3d6000fd5b60203d1061540d576101005180821061540d5780820390509050600a0a63000051ae52604e601263313ce567610140526020610140600461015c60c0515afa610239573d600060003e3d6000fd5b60203d1061540d576101405180821061540d5780820390509050101561540d57601263313ce567610140526020610140600461015c60c0515afa610282573d600060003e3d6000fd5b60203d1061540d576101405180821061540d5780820390509050600a0a63000051ce5261514e6102be63000000003961514e60a0016300000000f3600436101561000d576121cb565b60003560e01c346151495763fc0c546a811861003757602061514e60003960005160405260206040f35b63c6610657811861007457602061516e600039600051604052602061518e6000396000516060526020602060043560028110156151495702604001f35b63f446c1d0811861009157602061008c610120613290565b610120f35b63b137392981186100b45760206100a9610120613290565b610120602081019050f35b63ddca3f4381186100fb5760206100cb60c0613221565b60c08051610120526020810151610140525061012051604052610140516060526100f66101006133ed565b610100f35b63bb7b8b80811861018c57670de0b6b3a7640000601954610160526101216101e06134f9565b6101e05180820282158284830414171561514957905090506318160ddd610200526020610200600461021c602061514e6000396000515afa610168573d600060003e3d6000fd5b60203d10615149576102005180801561514957820490509050610240526020610240f35b6386fc88d381186101a95760206101a46102406138ac565b610240f35b635b41b90881186101be5733610d20526101d9565b63a64833a0811861023a576084358060a01c61514957610d20525b600054615149576001600055602033610900526080600461092037610d20516109a05260006109c0526004610d40526000610d6052610d408051806109e052602082018051610a0052505050610230610d80614103565b610d806000600055f35b63b8ca1ad781186102fd576084358060a01c61514957610d205260a4358060a01c61514957610d405260c435600401600481351161514957803580610d6052602082018035610d80525050506000546151495760016000556004610de0526000610e0052610de0805160208201209050610d6051610d802014615149576020610d2051610900526080600461092037610d40516109a052336109c052610d6051806109e052610d8051610a0052506102f3610da0614103565b610da06000600055f35b63556d6e9f81186105c45760243560043514615149576002600435101561514957600260243510156151495760015460206151ce60003960005180820282158284830414171561514957905090506104005260175461042052601854610440526103686104a0613290565b6104a0805161046052602081015161048052506019546104a052600060085411156103ef57610460516105205261048051610540526103a86104c0613221565b6104c08051610560526020810151610580525061052051610160526105405161018052610560516101a052610580516101c0526103e661050061234d565b610500516104a0525b602060043560028110156151495702610420018051604435818183011061514957808201905090508152506104205160206151ae60003960005180820282158284830414171561514957905090506104205261044051610400518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610440526104605160405261048051606052610420516080526104405160a0526104a05160c05260243560e0526104a56104e06129f9565b6104e0516104c05260206024356002811015615149570261042001516104c0518082106151495780820390509050600180821061514957808203905090506104e0526104c051602060243560028110156151495702610420015260006024351161052e576104e05160206151ae600039600051808015615149578204905090506104e052610565565b6104e051670de0b6b3a7640000808202821582848304141715615149579050905061040051808015615149578204905090506104e0525b6104e05161042051604052610440516060526105826105006133ed565b610500516104e05180820282158284830414171561514957905090506402540be4008082049050905080821061514957808203905090506104e05260206104e0f35b630b4c7e4d81186105d95733610900526105f4565b630c3e4b548118610eb1576064358060a01c61514957610900525b6000546151495760016000556020546151495760006004351161061c5760006024351161061f565b60015b156151495761062f610960613290565b61096080516109205260208101516109405250602061516e60003960005161096052602061518e600039600051610980526017546109a0526018546109c05260e0366109e0376109a051610ac0526109c051610ae05260006002905b80610b00526020610b0051600281101561514957026109a001516020610b0051600281101561514957026004013581818301106151495780820190509050610b2052610b20516020610b0051600281101561514957026109a00152610b2051610b00516002811015615149576017015560010181811861068b5750506109a051610a20526109c051610a405260015460206151ce6000396000518082028215828483041417156151495790509050610b00526109a05160206151ae60003960005180820282158284830414171561514957905090506109a0526109c051610b00518082028215828483041417156151495790509050670de0b6b3a7640000808204905090506109c052610ac05160206151ae6000396000518082028215828483041417156151495790509050610ac052610ae051610b00518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610ae05260006002905b80610b205260006020610b2051600281101561514957026004013511156108de576323b872dd610b405233610b605230610b80526020610b20516002811015615149570260040135610ba0526020610b406064610b5c60006020610b20516002811015615149570261096001515af161086f573d600060003e3d6000fd5b60203d1061514957610b40518060011c61514957610bc052610bc05115615149576020610b2051600281101561514957026109a001516020610b205160028110156151495702610ac0015180821061514957808203905090506020610b2051600281101561514957026109e001525b6001018181186107f15750506000600435116108ff57600060243511610902565b60015b1561514957600854610b20526000610b20511161092557601954610aa052610968565b61092051610160526109405161018052610ac0516101a052610ae0516101c052610950610b4061234d565b610b4051610aa052610b205142106109685760016008555b610920516101605261094051610180526109a0516101a0526109c0516101c052610993610b6061234d565b610b6051610b40526318160ddd610b80526020610b806004610b9c602061514e6000396000515afa6109ca573d600060003e3d6000fd5b60203d1061514957610b8051610b60526000610aa05111610a0557610b4051610160526109f8610b806134f9565b610b8051610a6052610a49565b610b6051610b40518082028215828483041417156151495790509050610aa05180801561514957820490509050610b60518082106151495780820390509050610a60525b6000610a60511115615149576000610aa05111610ae157610b4051601955670de0b6b3a7640000601e55670de0b6b3a7640000601c556340c10f19610b805261090051610ba052610a6051610bc0526020610b806044610b9c6000602061514e6000396000515af1610ac0573d600060003e3d6000fd5b60203d1061514957610b80518060011c61514957610be052610be050610de9565b6109e05160c052610a005160e0526109a051610100526109c05161012052610b0a610b806149f0565b610b8051610a605180820282158284830414171561514957905090506402540be40080820490509050600181818301106151495780820190509050610a8052610a6051610a80518082106151495780820390509050610a6052610b6051610a605181818301106151495780820190509050610b60526340c10f19610b805261090051610ba052610a6051610bc0526020610b806044610b9c6000602061514e6000396000515af1610bc0573d600060003e3d6000fd5b60203d1061514957610b80518060011c61514957610be052610be0506000610b8052620186a0610a60511115610db15760043515610c015760243515610c04565b60015b15610db157606036610ba03760043515610c5357610a405160206151ce6000396000518082028215828483041417156151495790509050610ba05260206151ae600039600051610bc052610c90565b610a205160206151ae6000396000518082028215828483041417156151495790509050610ba05260206151ce600039600051610bc0526001610be0525b610ba051610a60518082028215828483041417156151495790509050610b605180801561514957820490509050610ba052610ba051670de0b6b3a764000080820282158284830414171561514957905090506020610be0516002811015615149570260040135610bc0518082028215828483041417156151495790509050610a60516020610be05160028110156151495702610a2001518082028215828483041417156151495790509050610bc0518082028215828483041417156151495790509050610b605180801561514957820490509050808210615149578082039050905080801561514957820490509050610b8052610be051610db1576ec097ce7bc90715b34b9f1000000000610b805180801561514957820490509050610b80525b610920516106005261094051610620526109a051610640526109c05161066052610b805161068052610b40516106a052610de961398d565b604435610a60511015610e5c576008610b80527f536c697070616765000000000000000000000000000000000000000000000000610ba052610b8050610b805180610ba00181600003601f1636823750506308c379a0610b40526020610b6052601f19601f610b80510116604401610b5cfd5b610900517f540ab385f9b5d450a27404172caade516b3ba3f4be88239ac56a2ad1de2a1f5a600435610b8052602435610ba052610a8051610bc052610b6051610be0526080610b80a26020610a606000600055f35b635b36389c8118610ec55733604052610edf565b633eb1719f8118611182576064358060a01c615149576040525b600054615149576001600055602061516e600039600051606052602061518e6000396000516080526318160ddd60c052602060c0600460dc602061514e6000396000515afa610f33573d600060003e3d6000fd5b60203d106151495760c05160a0526379cc679060c0523360e05260043561010052602060c0604460dc6000602061514e6000396000515af1610f7a573d600060003e3d6000fd5b60203d106151495760c0518060011c61514957610120526101205060175460c05260185460e052600435600180821061514957808203905090506101005260006002905b80610120526020610120516002811015615149570260c0015161010051808202821582848304141715615149579050905060a051808015615149578204905090506101405260206101205160028110156151495702602401356101405110615149576020610120516002811015615149570260c001516101405180821061514957808203905090506101205160028110156151495760170155610140516020610120516002811015615149570260c0015263a9059cbb6101605260405161018052610140516101a0526020610160604461017c600060206101205160028110156151495702606001515af16110b8573d600060003e3d6000fd5b60203d1061514957610160518060011c615149576101c0526101c0511561514957600101818118610fbe57505060195461012052610120516101205161010051808202821582848304141715615149579050905060a051808015615149578204905090508082106151495780820390509050601955337fdd3c0336a16f1b64f172b7bb0dad5b2b3c7c76f91e8c4aafd6aae60dce80015360c0516101405260e0516101605260a0516004358082106151495780820390509050610180526060610140a26000600055005b638d8ea72781186113f8576318160ddd610420526020610420600461043c602061514e6000396000515afa6111bc573d600060003e3d6000fd5b60203d1061514957610420516104005260015460206151ce6000396000518082028215828483041417156151495790509050610420526111fd610480613290565b6104808051610440526020810151610460525061121b6104c0613221565b6104c080516104805260208101516104a0525060043560206151ae60003960005180820282158284830414171561514957905090506104c052602435610420518082028215828483041417156151495790509050670de0b6b3a7640000808204905090506104e05260195461050052600060085411156112c95761044051610160526104605161018052610480516101a0526104a0516101c0526112c061052061234d565b61052051610500525b610480516104c05181818301106151495780820190509050610480526104a0516104e051818183011061514957808201905090506104a05261044051610160526104605161018052610480516101a0526104a0516101c05261132c61054061234d565b610540516105205261040051610520518082028215828483041417156151495790509050610500518080156151495782049050905061040051808210615149578082039050905061054052610540516104c05160c0526104e05160e05261048051610100526104a051610120526113a46105606149f0565b610560516105405180820282158284830414171561514957905090506402540be400808204905090506001818183011061514957808201905090508082106151495780820390509050610540526020610540f35b634fb08c5e81186114775760206114106106a0613290565b6106a080516107805260208101516107a05250604060046107c03760016108005260006108205261078051610400526107a051610420526107c051610440526107e051610460526108005161048052610820516104a0526114726106e0614b5a565b6106e0f35b63f1dc3cc9811861148c5733610900526114a7565b630fbcee6e8118611751576064358060a01c61514957610900525b600054615149576001600055602054615149576114c5610960613290565b6109608051610920526020810151610940525060a03661096037600854610a00526109205161040052610940516104205260406004610440376000610a0051116104805260016104a05261151a610a20614b5a565b610a2080516109605260208101516109a0526040810151610980526060810180516109c05260208101516109e05250506044356109605110156115bd576008610a20527f536c697070616765000000000000000000000000000000000000000000000000610a4052610a2050610a205180610a400181600003601f1636823750506308c379a06109e0526020610a0052601f19601f610a205101166044016109fcfd5b610a005142106115cd5760016008555b60243560028110156151495760170180546109605180821061514957808203905090508155506379cc6790610a205233610a4052600435610a60526020610a206044610a3c6000602061514e6000396000515af1611630573d600060003e3d6000fd5b60203d1061514957610a20518060011c61514957610a8052610a8050602061516e600039600051610a2052602061518e600039600051610a405263a9059cbb610a605261090051610a805261096051610aa0526020610a606044610a7c6000602060243560028110156151495702610a2001515af16116b4573d600060003e3d6000fd5b60203d1061514957610a60518060011c61514957610ac052610ac0511561514957610920516106005261094051610620526109c051610640526109e051610660526109a05161068052610980516106a05261170d61398d565b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a060406004610a603761096051610aa0526060610a60a260206109606000600055f35b63c93f49e8811861177757600054615149576001600055611770613576565b6000600055005b635e248072811861196e57601a543318615149576007546201517f8181830110615149578082019050905042111561514957426201517f818183011061514957808201905090506044351115615149576117d2610160613290565b610160805161012052602081015161014052506101205160801b6101605261014051610160511761016052610f9f60043511156151495763ee6b28016004351015615149576402540be3ff60243511156151495766470de4df820001602435101561514957670de0b6b3a76400006004358082028215828483041417156151495790509050610120518080156151495782049050905061018052678ac7230489e800016101805110156151495767016345785d89ffff61018051111561514957670de0b6b3a76400006024358082028215828483041417156151495790509050610140518080156151495782049050905061018052678ac7230489e800016101805110156151495767016345785d89ffff61018051111561514957610160516005554260075560043560801b6101a0526024356101a051176101a0526044356008556101a0516006557fe35f0559b0642164e286b30df2077ec3a05426617a25db7578fd20ba39a6cd05610120516101c0526004356101e05261014051610200526024356102205242610240526044356102605260c06101c0a1005b63244c7c2e8118611a0c57601a5433186151495761198d610160613290565b610160805161012052602081015161014052506101205160801b6101605261014051610160511761016052610160516005556101605160065542600755426008557f5f0e7fba3d100c9e19446e1c92fe436f0a9a22fe99669360e4fdd6d3de2fc2846101205161018052610140516101a052426101c0526060610180a1005b63a43c33518118611bb657601a543318615149576023546151495760e060046040376402540be40160605110611a4757601254606052611a55565b6207a11f6060511115615149575b6402540be4006040511115611a6b576011546040525b60605160405111615149576402540be4006080511115611a8c576013546080525b670de0b6b3a764000060a05110611aa857600b5460a052611ab4565b600060a0511115615149575b670de0b6b3a764000060c0511115611acd5760095460c0525b670de0b6b3a764000060e0511115611ae657600d5460e0525b62093a806101005110611aff57600f5461010052611b0c565b6000610100511115615149575b426203f48081818301106151495780820190509050610120526101205160235560805160165560405160145560605160155560a051600c5560c051600a5560e051600e5561010051601055610120517f913fde9a37e1f8ab67876a4d0ce80790d764fcfc5692f4529526df9c6bdde55360805161014052604051610160526060516101805260a0516101a05260c0516101c05260e0516101e052610100516102005260e0610140a2005b632a7dd7cd8118611ccb57600054615149576001600055601a54331861514957602354421061514957600060235414615149576000602355601654610600526106005160135414611c1157611c09613576565b610600516013555b60145461062052610620516011556015546106405261064051601255600c546106605261066051600b55600a546106805261068051600955600e546106a0526106a051600d556010546106c0526106c051600f557f1c65bbdc939f346e5d6f0bde1f072819947438d4fc7b182cc59c2f6dc5504087610600516106e05261062051610700526106405161072052610660516107405261068051610760526106a051610780526106c0516107a05260e06106e0a16000600055005b63226840fb8118611ce657601a543318615149576000602355005b636b441a408118611d61576004358060a01c61514957604052601a5433186151495760225461514957426203f48081818301106151495780820190509050606052606051602255604051601b556040516060517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb93560006080a3005b636a1c05ae8118611dc457601a54331861514957602254421061514957600060225414615149576000602255601b54604052604051601a556040517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c60006060a2005b6386fbf1938118611ddf57601a543318615149576000602255005b63e36988538118611e0457601a54331861514957426021541115615149576001602055005b633046f9728118611e1f57601a543318615149576000602055005b637242e5248118611e49576004358060a01c61514957604052601a54331861514957604051602455005b6354f0f7d58118611ec5576002601e548082028215828483041417156151495790509050611e786102406138ac565b610240516102805261028051604052611e92610260615027565b610260518082028215828483041417156151495790509050670de0b6b3a7640000808204905090506102a05260206102a0f35b63b9e8c9fd8118611edc5760015460405260206040f35b63c146bf948118611ef35760035460405260206040f35b636112c7478118611f0a5760045460405260206040f35b63204fe3d58118611f215760055460405260206040f35b63f30cfad58118611f385760065460405260206040f35b63e89876ff8118611f4f5760075460405260206040f35b63f9ed95978118611f665760085460405260206040f35b6349fe9e778118611f7d5760095460405260206040f35b63727ced578118611f9457600a5460405260206040f35b6372d4f0e28118611fab57600b5460405260206040f35b63d7c3dcbe8118611fc257600c5460405260206040f35b63083812e58118611fd957600d5460405260206040f35b634ea12c7d8118611ff057600e5460405260206040f35b63662b6274811861200757600f5460405260206040f35b630c5e23d4811861201e5760105460405260206040f35b6392526c0c81186120355760115460405260206040f35b63ee8de675811861204c5760125460405260206040f35b63fee3f7f981186120635760135460405260206040f35b637cf9aedc811861207a5760145460405260206040f35b637d1b060c81186120915760155460405260206040f35b63e382446281186120a85760165460405260206040f35b634903b0d181186120cc576004356002811015615149576017015460405260206040f35b630f529ba281186120e35760195460405260206040f35b638da5cb5b81186120fa57601a5460405260206040f35b631ec0cdc1811861211157601b5460405260206040f35b637ba1a74d811861212857601c5460405260206040f35b630b7b594b811861213f57601d5460405260206040f35b630c46b72a811861215657601e5460405260206040f35b639c868ac0811861216d5760205460405260206040f35b632a42689681186121845760215460405260206040f35b63e0a0b586811861219b5760225460405260206040f35b63405e28f881186121b25760235460405260206040f35b636e42e4d281186121c95760245460405260206040f35b505b60006000fd5b60405160a05260605160c0526080516121eb5760006121f3565b60c05160a051105b156122055760605160a05260405160c0525b60a05160e052600061010052600060ff905b806101205260e05161014052600260e05160a05160c051808202821582848304141715615149579050905060e05180801561514957820490509050818183011061514957808201905090500460e0526101405160e051116122835760e051610140510361010052612290565b6101405160e05103610100525b60016101005111156122c65760e05161010051670de0b6b3a76400008082028215828483041417156151495790509050106122c9565b60015b156122db5760e051835250505061234b565b6001018181186122175750506010610120527f446964206e6f7420636f6e766572676500000000000000000000000000000000610140526101205061012051806101400181600003601f1636823750506308c379a060e052602061010052601f19601f61012051011660440160fcfd5b565b610f9f610160511161236057600061236b565b63ee6b280161016051105b15615149576402540be3ff6101805111612386576000612394565b66470de4df82000161018051105b15615149576101a0516101e0526101c05161020052610200516101e05110156123c8576101c0516101e0526101a051610200525b633b9ac9ff6101e051116123dd5760006123f2565b6d314dc6448d9338c15b0a000000016101e051105b1561514957655af3107a3fff61020051670de0b6b3a764000080820282158284830414171561514957905090506101e0518080156151495782049050905011156151495760026101e0516040526102005160605260006080526124566102406121d1565b610240518082028215828483041417156151495790509050610220526101e05161020051818183011061514957808201905090506102405261018051670de0b6b3a76400008181830110615149578082019050905061026052600060ff905b8061028052610220516102a0526000610220511115615149576102205161022051673782dace9d9000006101e051808202821582848304141715615149579050905004610200518082028215828483041417156151495790509050046102c052610260516102e0526102c0516102e0511161254e576102e0516102c051036001818183011061514957808201905090506102e05261256e565b6102c0516102e051036001818183011061514957808201905090506102e0525b610160516101805161018051670de0b6b3a7640000610220518082028215828483041417156151495790509050046102e0518082028215828483041417156151495790509050046102e0518082028215828483041417156151495790509050612710808202821582848304141715615149579050905004610300526102e051673782dace9d9000006102c0518082028215828483041417156151495790509050046103205261024051670de0b6b3a764000061024051610320518082028215828483041417156151495790509050048181830110615149578082019050905061030051600280820282158284830414171561514957905090506102c0518080156151495782049050905081818301106151495780820190509050670de0b6b3a76400006103205161022051808202821582848304141715615149579050905004808210615149578082039050905061034052610220516103405161024051818183011061514957808201905090508082028215828483041417156151495790509050610340518080156151495782049050905061036052610220516102205180820282158284830414171561514957905090506103405180801561514957820490509050610380526102c051670de0b6b3a7640000116127cd5761038051670de0b6b3a764000061022051610300516103405180801561514957820490509050808202821582848304141715615149579050905004670de0b6b3a76400006102c0510380820282158284830414171561514957905090506102c05180801561514957820490509050808210615149578082039050905061038052612850565b61038051670de0b6b3a7640000610220516103005161034051808015615149578204905090508082028215828483041417156151495790509050046102c051670de0b6b3a76400000380820282158284830414171561514957905090506102c0518080156151495782049050905081818301106151495780820190509050610380525b6103805161036051116128725760026103605161038051030461022052612880565b610380516103605103610220525b60006103a0526102a05161022051116128a557610220516102a051036103a0526128b3565b6102a05161022051036103a0525b6102205180662386f26fc10000811882662386f26fc1000011021890506103a051655af3107a4000808202821582848304141715615149579050905010156129855760006002905b602081026101e001516103c0526103c051670de0b6b3a7640000808202821582848304141715615149579050905061022051808015615149578204905090506103e052662386f26fc0ffff6103e05111612956576000612966565b68056bc75e2d631000016103e051105b15615149576001018181186128fb5750506102205183525050506129f7565b6001018181186124b55750506010610280527f446964206e6f7420636f6e7665726765000000000000000000000000000000006102a0526102805061028051806102a00181600003601f1636823750506308c379a061024052602061026052601f19601f61028051011660440161025cfd5b565b610f9f60405111612a0b576000612a15565b63ee6b2801604051105b15615149576402540be3ff60605111612a2f576000612a3c565b66470de4df820001606051105b156151495767016345785d89ffff60c05111612a59576000612a6d565b6d314dc6448d9338c15b0a0000000160c051105b15615149576020600160e051808210615149578082039050905060028110156151495702608001516101005270010000000000000000000000000000000060c051101561514957600260c0510a61010051600480820282158284830414171561514957905090508080156151495782049050905061012052671bc16d674ec8000061010051808202821582848304141715615149579050905060c051808015615149578204905090506101405266470de4df81ffff6101405111612b32576000612b42565b680ad78ebc5ac620000161014051105b156151495761010051655af3107a40008082049050905060c051655af3107a400080820490509050808281188284110218905090506064818118606483110218905061016052606051670de0b6b3a76400008181830110615149578082019050905061018052600060ff905b806101a052610120516101c05260c0516101405161012051808202821582848304141715615149579050905060028082028215828483041417156151495790509050046101e0526101005161012051818183011061514957808201905090506102005261018051610220526101e0516102205111612c4a57610220516101e0510360018181830110615149578082019050905061022052612c6a565b6101e0516102205103600181818301106151495780820190509050610220525b604051606051606051670de0b6b3a764000060c051808202821582848304141715615149579050905004610220518082028215828483041417156151495790509050046102205180820282158284830414171561514957905090506127108082028215828483041417156151495790509050046102405261022051670de0b6b3a7640000671bc16d674ec800006101e0518082028215828483041417156151495790509050818183011061514957808201905090500461026052670de0b6b3a7640000610120518082028215828483041417156151495790509050610200516102605180820282158284830414171561514957905090508181830110615149578082019050905061024051818183011061514957808201905090506102805260c0516102605180820282158284830414171561514957905090506102a0526102a0516102805110612dc7576102a051610280510361028052612dd7565b60026101c0510461012052612fc7565b6102805161012051808015615149578204905090506102c052610240516102c051808015615149578204905090506102e05261028051670de0b6b3a764000060c0518082028215828483041417156151495790509050818183011061514957808201905090506102c051808015615149578204905090506102e051670de0b6b3a764000080820282158284830414171561514957905090506101e0518080156151495782049050905081818301106151495780820190509050610300526102e051670de0b6b3a76400006102005180820282158284830414171561514957905090506102c05180801561514957820490509050818183011061514957808201905090506102e0526102e0516103005110612efd576102e051610300510361012052612f09565b60026101c05104610120525b6000610320526101c0516101205111612f2e57610120516101c0510361032052612f3c565b6101c0516101205103610320525b61016051655af3107a4000610120510480828118828411021890509050610320511015612fc75760c05161012051670de0b6b3a764000080820282158284830414171561514957905090500461034052662386f26fc0ffff6103405111612fa4576000612fb4565b68056bc75e2d6310000161034051105b1561514957610120518352505050613039565b600101818118612bae57505060106101a0527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101c0526101a0506101a051806101c00181600003601f1636823750506308c379a061016052602061018052601f19601f6101a051011660440161017cfd5b565b670de0b6b3a764000060405104606052603b606051111561306057600081525061321f565b670de0b6b3a7640000606051026040510360805260605160020a60a05260a051670de0b6b3a76400000460a05260805161309f5760a05181525061321f565b670de0b6b3a764000060c052670de0b6b3a764000060e052600061010052600160ff8101905b8061012052670de0b6b3a7640000610120510261014052670de0b6b3a7640000610140510361016052610160516080511161310b57608051610160510361016052613121565b6101605160805103610160526101005115610100525b610140516002610160510460c051020460c0526101005161315a5760e05160c0518181830110615149578082019050905060e052613172565b60e05160c051808210615149578082039050905060e0525b6402540be40060c05110156131af57670de0b6b3a764000060a05160e051808202821582848304141715615149579050905004835250505061321f565b6001018181186130c55750506010610120527f446964206e6f7420636f6e766572676500000000000000000000000000000000610140526101205061012051806101400181600003601f1636823750506308c379a060e052602061010052601f19601f61012051011660440160fcfd5b565b60175460206151ae60003960005180820282158284830414171561514957905090508152670de0b6b3a764000060185460206151ce6000396000518082028215828483041417156151495790509050600154808202821582848304141715615149579050905004602082015250565b6008546040526006546060526fffffffffffffffffffffffffffffffff6060511660805260605160801c60a0526040514210156133dd5760055460c05260075460e05260405160e05180821061514957808203905090506040524260e051808210615149578082039050905060e05260405160e05180821061514957808203905090506101005260c05160801c61010051808202821582848304141715615149579050905060a05160e0518082028215828483041417156151495790509050818183011061514957808201905090506040518080156151495782049050905060a0526fffffffffffffffffffffffffffffffff60c0511661010051808202821582848304141715615149579050905060805160e051808202821582848304141715615149579050905081818301106151495780820190509050604051808015615149578204905090506080525b60a0518152608051602082015250565b600b546080526040516060518181830110615149578082019050905060a052670de0b6b3a764000060805102670de0b6b3a76400006080510160a051673782dace9d900000604051808202821582848304141715615149579050905060a0518080156151495782049050905060605180820282158284830414171561514957905090500480821061514957808203905090508080156151495782049050905060a052670de0b6b3a764000060115460a0518082028215828483041417156151495790509050601254670de0b6b3a764000060a051808210615149578082039050905080820282158284830414171561514957905090508181830110615149578082019050905004815250565b600261016051046101805261016051670de0b6b3a7640000808202821582848304141715615149579050905060015460028082028215828483041417156151495790509050808015615149578204905090506101a052610180516040526101a051606052600160805261356d6101c06121d1565b6101c051815250565b613581610440613290565b61044080516104005260208101516104205250601c5461044052601d5461046052602061516e60003960005161048052602061518e6000396000516104a05260006002905b806104c0526370a082316104e052306105005260206104e060246104fc60206104c0516002811015615149570261048001515afa613609573d600060003e3d6000fd5b60203d10615149576104e0516104c051600281101561514957601701556001018181186135c6575050601e546104c052610460516104405111156137a5576404a817c800610440516104605180821061514957808203905090506013548082028215828483041417156151495790509050046104e05260006104e05111156137a55760245461050052600061050051146137a5576104c051670de0b6b3a764000080820282158284830414171561514957905090506104c0516104e051808210615149578082039050905080801561514957820490509050670de0b6b3a7640000808210615149578082039050905061052052636962f845610560526105005161058052610520516105a0526020610560604461057c6000602061514e6000396000515af161373d573d600060003e3d6000fd5b60203d106151495761056051610540526104405160026104e0510280821061514957808203905090506104405261044051601c55610500517f6059a38198b1dc42b3791087d1ff0fbd72b3179553c25f678cd246f52ffaaf5961054051610560526020610560a25b6318160ddd610500526020610500600461051c602061514e6000396000515afa6137d4573d600060003e3d6000fd5b60203d1061514957610500516104e0526104005161058052610420516105a0526137ff610520613221565b61052080516105c05260208101516105e0525061058051610160526105a051610180526105c0516101a0526105e0516101c05261383d61056061234d565b610560516105005261050051601955670de0b6b3a764000061050051610160526138686105206134f9565b6105205180820282158284830414171561514957905090506104e05180801561514957820490509050601e55610460516104405111156138aa5761044051601d555b565b600254610180526004546101a052426101a051106138d4576101805181525061398b5661398b565b600f546101c0526003546101e0526101c051670de0b6b3a7640000426101a0518082106151495780820390509050020460405261391261022061303b565b6102205161020052670de0b6b3a76400006101e051670de0b6b3a7640000610200518082106151495780820390509050808202821582848304141715615149579050905061018051610200518082028215828483041417156151495790509050818183011061514957808201905090500481525061398b565b565b6002546106c0526003546106e052600154610700526004546107205260006107405242610720511015613a7257600f546107605261076051670de0b6b3a76400004261072051808210615149578082039050905002046040526139f16107a061303b565b6107a05161078052670de0b6b3a76400006106e051670de0b6b3a764000061078051808210615149578082039050905080820282158284830414171561514957905090506106c05161078051808202821582848304141715615149579050905081818301106151495780820190509050046106c0526106c051600255426004555b6106a051610760526106a051613ab65761060051610160526106205161018052610640516101a052610660516101c052613aad61078061234d565b61078051610760525b60006106805111613b75576106405161078052610660516107a052620f424061078051046107c052610780516107c0518181830110615149578082019050905061078052610700516107c0518082028215828483041417156151495790509050610660516106005160405261062051606052610780516080526107a05160a0526107605160c052600160e052613b4d6107e06129f9565b6107e0518082106151495780820390509050808015615149578204905090506106e052613b7e565b610680516106e0525b6106e0516003556318160ddd6107a05260206107a060046107bc602061514e6000396000515afa613bb4573d600060003e3d6000fd5b60203d10615149576107a05161078052601c546107a052601e546107c052600261076051046107e05261076051670de0b6b3a7640000808202821582848304141715615149579050905060026107005180820282158284830414171561514957905090508080156151495782049050905061080052670de0b6b3a764000061082052670de0b6b3a76400006108405260006107c0511115613d79576107e051604052610800516060526001608052613c6d6108806121d1565b6108805161086052670de0b6b3a76400006108605180820282158284830414171561514957905090506107805180801561514957820490509050610840526107a0516108405180820282158284830414171561514957905090506107c0518080156151495782049050905061082052600854610880526107c0516108405110613cf7576000613cfd565b61088051155b15613d685760046108a0527f4c6f7373000000000000000000000000000000000000000000000000000000006108c0526108a0506108a051806108c00181600003601f1636823750506308c379a061086052602061088052601f19601f6108a051011660440161087cfd5b60016108805118613d795760006008555b61082051601c556106c051670de0b6b3a76400008082028215828483041417156151495790509050610700518080156151495782049050905061086052670de0b6b3a76400006108605111613ddf5761086051670de0b6b3a76400000361086052613df2565b670de0b6b3a76400006108605103610860525b600d54600a61086051048082811882841102189050905061088052601f546108a0526108a05115613e24576000613e97565b61082051600260095402818183011061514957808201905090506108405160028082028215828483041417156151495790509050670de0b6b3a7640000808210615149578082039050905011613e7b576000613e97565b610880516108605111613e8f576000613e97565b60006107c051115b15613ea85760016108a0526001601f555b6108a051156140dd57610880516108605111613ec5576000613ecd565b60006107c051115b156140dd576108605161070051610860516108805180821061514957808203905090508082028215828483041417156151495790509050610880516106c0518082028215828483041417156151495790509050818183011061514957808201905090500461074052610640516107e05261066051610740518082028215828483041417156151495790509050610700518080156151495782049050905061080052610600516101605261062051610180526107e0516101a052610800516101c052613f996108e061234d565b6108e0516108c05260026108c051046107e0526108c051670de0b6b3a7640000808202821582848304141715615149579050905060026107405180820282158284830414171561514957905090508080156151495782049050905061080052670de0b6b3a76400006107e05160405261080051606052600160805261401f6108e06121d1565b6108e051808202821582848304141715615149579050905061078051808015615149578204905090506107c052670de0b6b3a76400006107c0511161406557600061409c565b6108205160026107c0518082028215828483041417156151495790509050670de0b6b3a76400008082106151495780820390509050115b6140c3576000601f556107605160195561084051601e5561410161357656614101566140dd565b610740516001556108c0516019556107c051601e55614101565b6107605160195561084051601e556108a05115614101576000601f55614101613576565b565b6020546151495761094051610920511461514957600261092051101561514957600261094051101561514957600061096051111561514957614146610a60613290565b610a608051610a20526020810151610a405250601754610a6052601854610a8052604036610aa037602061516e600039600051610ae052602061518e600039600051610b005260206109405160028110156151495702610a600151610b205260206109205160028110156151495702610a600151610b4052610b4051610960518181830110615149578082019050905060206109205160028110156151495702610a60015260206109205160028110156151495702610a6001516109205160028110156151495760170155600154610b6052610a605160206151ae6000396000518082028215828483041417156151495790509050610a6052610a8051610b6051808202821582848304141715615149579050905060206151ce6000396000518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610a805260206151ae600039600051610b805260206151ce600039600051610ba052600161092051186142d65760206151ce600039600051610b805260206151ae600039600051610ba0525b600854610bc0526000610bc05111156143d357610b4051610b80518082028215828483041417156151495790509050610b4052600061092051111561434657610b4051610b60518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610b40525b60206109205160028110156151495702610a600151610be052610b405160206109205160028110156151495702610a600152610a205161016052610a405161018052610a60516101a052610a80516101c0526143a3610c0061234d565b610c0051601955610be05160206109205160028110156151495702610a600152610bc05142106143d35760016008555b60206109405160028110156151495702610a600151610a2051604052610a4051606052610a6051608052610a805160a05260195460c0526109405160e05261441c610be06129f9565b610be0518082106151495780820390509050610ac05260206109405160028110156151495702610a60018051610ac0518082106151495780820390509050815250610ac05160018082106151495780820390509050610ac05260006109405111156144b857610ac051670de0b6b3a76400008082028215828483041417156151495790509050610b605180801561514957820490509050610ac0525b610ac051610ba05180801561514957820490509050610ac052610ac051610a6051604052610a80516060526144ee610be06133ed565b610be051610ac05180820282158284830414171561514957905090506402540be400808204905090508082106151495780820390509050610ac05261098051610ac051101561459d576008610be0527f536c697070616765000000000000000000000000000000000000000000000000610c0052610be050610be05180610c000181600003601f1636823750506308c379a0610ba0526020610bc052601f19601f610be0510116604401610bbcfd5b610b2051610ac0518082106151495780820390509050610b2052610b205161094051600281101561514957601701556004610c20526000610c4052610c208051602082012090506109e051610a002018614667576323b872dd610c605261090051610c805230610ca05261096051610cc0526020610c606064610c7c600060206109205160028110156151495702610ae001515af1614641573d600060003e3d6000fd5b60203d1061514957610c60518060011c61514957610ce052610ce05115615149576147a6565b60206109205160028110156151495702610ae00151610be0526370a08231610c205230610c40526020610c206024610c3c610be0515afa6146ad573d600060003e3d6000fd5b60203d1061514957610c2051610c005260006109e05181610c4001610a00518152508082019150506109005181610c4001526020810190506109a05181610c400152602081019050610be05181610c4001526020810190506109605181610c400152602081019050610ac05181610c40015260208101905080610c2052610c20505060006000610c2051610c4060006109c0515af1614751573d600060003e3d6000fd5b610960516370a08231610c205230610c40526020610c206024610c3c610be0515afa614782573d600060003e3d6000fd5b60203d1061514957610c2051610c0051808210615149578082039050905018615149575b63a9059cbb610be0526109a051610c0052610ac051610c20526020610be06044610bfc600060206109405160028110156151495702610ae001515af16147f1573d600060003e3d6000fd5b60203d1061514957610be0518060011c61514957610c4052610c40511561514957610b2051610ba0518082028215828483041417156151495790509050610b2052600061094051111561486f57610b2051610b60518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610b20525b610b205160206109405160028110156151495702610a600152620186a0610960511161489c5760006148a6565b620186a0610ac051115b156149665761096051610b80518082028215828483041417156151495790509050610be052610ac051610ba0518082028215828483041417156151495790509050610c0052610920511561492f57610c0051670de0b6b3a76400008082028215828483041417156151495790509050610be05180801561514957820490509050610aa052614966565b610be051670de0b6b3a76400008082028215828483041417156151495790509050610c005180801561514957820490509050610aa0525b610a205161060052610a405161062052610a605161064052610a805161066052610aa0516106805260006106a05261499c61398d565b610900517fb2e76ae99761dc136e598d4a629bb347eccb9532a5f8bbd72e18467c3c34cc9861092051610be05261096051610c005261094051610c2052610ac051610c40526080610be0a2610ac051815250565b6101005160405261012051606052614a096101606133ed565b61016051600280820282158284830414171561514957905090506004808204905090506101405260006101605260006002905b6020810260c001516101805261016051610180518181830110615149578082019050905061016052600101818118614a3c575050610160516002808204905090506101805260006101a05260006002905b6020810260c001516101c052610180516101c05111614ad9576101a051610180516101c0518082106151495780820390509050818183011061514957808201905090506101a052614b08565b6101a0516101c051610180518082106151495780820390509050818183011061514957808201905090506101a0525b600101818118614a8d575050610140516101a05180820282158284830414171561514957905090506101605180801561514957820490509050620186a081818301106151495780820190509050815250565b6318160ddd6104e05260206104e060046104fc602061514e6000396000515afa614b89573d600060003e3d6000fd5b60203d10615149576104e0516104c0526104c0516104405111615149576002610460511015615149576017546104e0526018546105005260006105205260015460206151ce6000396000518082028215828483041417156151495790509050610540526104e05160206151ae60003960005180820282158284830414171561514957905090506105605261050051610540518082028215828483041417156151495790509050670de0b6b3a7640000808204905090506105805261046051614c7857670de0b6b3a764000060206151ae6000396000518082028215828483041417156151495790509050610540525b61048051614c8c5760195461052052614cc0565b61040051610160526104205161018052610560516101a052610580516101c052614cb76105a061234d565b6105a051610520525b610520516105a0526105605160405261058051606052614ce16105e06133ed565b6105e0516105c052610440516105a05180820282158284830414171561514957905090506104c051808015615149578204905090506105e0526105a0516105e0516105c0516105e05180820282158284830414171561514957905090506404a817c80080820490509050600181818301106151495780820190509050808210615149578082039050905080821061514957808203905090506105a0526104005160405261042051606052610560516080526105805160a0526105a05160c0526104605160e052614db26106206129f9565b6106205161060052602061046051600281101561514957026105600151610600518082106151495780820390509050670de0b6b3a76400008082028215828483041417156151495790509050610540518080156151495782049050905061062052610600516020610460516002811015615149570261056001526000610640526104a051614e41576000614e5f565b620186a06106205111614e55576000614e5f565b620186a061044051115b15614ff85760006106605260206151ae6000396000516106805260016104605118614ebf576104e05160206151ae60003960005180820282158284830414171561514957905090506106605260206151ce60003960005161068052614ee7565b6105005160206151ce6000396000518082028215828483041417156151495790509050610660525b610660516105e051808202821582848304141715615149579050905061052051808015615149578204905090506106605261066051670de0b6b3a76400008082028215828483041417156151495790509050610620516106805180820282158284830414171561514957905090506105e051602061046051600281101561514957026104e00151808202821582848304141715615149579050905061068051808202821582848304141715615149579050905061052051808015615149578204905090508082106151495780820390509050808015615149578204905090506106405261046051614ff8576ec097ce7bc90715b34b9f10000000006106405180801561514957820490509050610640525b6106205181526106405160208201526105a0516040820152606081016105605181526105805160208201525050565b604051615038576000815250615147565b604051670de0b6b3a7640000818183011061514957808201905090506002808204905090506060526040516080526000610100905b8060a05260805160605118615089576080518352505050615147565b606051608052604051670de0b6b3a76400008082028215828483041417156151495790509050606051808015615149578204905090506060518181830110615149578082019050905060028082049050905060605260010181811861506d575050601060a0527f446964206e6f7420636f6e76657267650000000000000000000000000000000060c05260a05060a0518060c00181600003601f1636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b565b600080fd005b600080fd000000000000000000000000cbaf0a32f5a16b326f00607421857f68fc72e5080000000000000000000000006f8eef407b974dff82c53ff939cc1ebb699383fb000000000000000000000000000000000000000000000000000000000bebc20000000000000000000000000000000000000000000000000000005af3107a400000000000000000000000000000000000000000000000000000000000004c4b400000000000000000000000000000000000000000000000000000000002aea54000000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000000000500918bd800000000000000000000000000000000000000000000000000000000012a05f20000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000d3e9777fd1e28800000000000000000000000000ca1c1ec4ebf3cc67a9f545ff90a3795b318ca4a000000000000000000000000cb444e90d8198415266c6a2724b7900fb12fc56e0000000000000000000000001337bedc9d22ecbe766df105c9623922a27963ec

Deployed Bytecode

0x600436101561000d576121cb565b60003560e01c346151495763fc0c546a811861003757602061514e60003960005160405260206040f35b63c6610657811861007457602061516e600039600051604052602061518e6000396000516060526020602060043560028110156151495702604001f35b63f446c1d0811861009157602061008c610120613290565b610120f35b63b137392981186100b45760206100a9610120613290565b610120602081019050f35b63ddca3f4381186100fb5760206100cb60c0613221565b60c08051610120526020810151610140525061012051604052610140516060526100f66101006133ed565b610100f35b63bb7b8b80811861018c57670de0b6b3a7640000601954610160526101216101e06134f9565b6101e05180820282158284830414171561514957905090506318160ddd610200526020610200600461021c602061514e6000396000515afa610168573d600060003e3d6000fd5b60203d10615149576102005180801561514957820490509050610240526020610240f35b6386fc88d381186101a95760206101a46102406138ac565b610240f35b635b41b90881186101be5733610d20526101d9565b63a64833a0811861023a576084358060a01c61514957610d20525b600054615149576001600055602033610900526080600461092037610d20516109a05260006109c0526004610d40526000610d6052610d408051806109e052602082018051610a0052505050610230610d80614103565b610d806000600055f35b63b8ca1ad781186102fd576084358060a01c61514957610d205260a4358060a01c61514957610d405260c435600401600481351161514957803580610d6052602082018035610d80525050506000546151495760016000556004610de0526000610e0052610de0805160208201209050610d6051610d802014615149576020610d2051610900526080600461092037610d40516109a052336109c052610d6051806109e052610d8051610a0052506102f3610da0614103565b610da06000600055f35b63556d6e9f81186105c45760243560043514615149576002600435101561514957600260243510156151495760015460206151ce60003960005180820282158284830414171561514957905090506104005260175461042052601854610440526103686104a0613290565b6104a0805161046052602081015161048052506019546104a052600060085411156103ef57610460516105205261048051610540526103a86104c0613221565b6104c08051610560526020810151610580525061052051610160526105405161018052610560516101a052610580516101c0526103e661050061234d565b610500516104a0525b602060043560028110156151495702610420018051604435818183011061514957808201905090508152506104205160206151ae60003960005180820282158284830414171561514957905090506104205261044051610400518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610440526104605160405261048051606052610420516080526104405160a0526104a05160c05260243560e0526104a56104e06129f9565b6104e0516104c05260206024356002811015615149570261042001516104c0518082106151495780820390509050600180821061514957808203905090506104e0526104c051602060243560028110156151495702610420015260006024351161052e576104e05160206151ae600039600051808015615149578204905090506104e052610565565b6104e051670de0b6b3a7640000808202821582848304141715615149579050905061040051808015615149578204905090506104e0525b6104e05161042051604052610440516060526105826105006133ed565b610500516104e05180820282158284830414171561514957905090506402540be4008082049050905080821061514957808203905090506104e05260206104e0f35b630b4c7e4d81186105d95733610900526105f4565b630c3e4b548118610eb1576064358060a01c61514957610900525b6000546151495760016000556020546151495760006004351161061c5760006024351161061f565b60015b156151495761062f610960613290565b61096080516109205260208101516109405250602061516e60003960005161096052602061518e600039600051610980526017546109a0526018546109c05260e0366109e0376109a051610ac0526109c051610ae05260006002905b80610b00526020610b0051600281101561514957026109a001516020610b0051600281101561514957026004013581818301106151495780820190509050610b2052610b20516020610b0051600281101561514957026109a00152610b2051610b00516002811015615149576017015560010181811861068b5750506109a051610a20526109c051610a405260015460206151ce6000396000518082028215828483041417156151495790509050610b00526109a05160206151ae60003960005180820282158284830414171561514957905090506109a0526109c051610b00518082028215828483041417156151495790509050670de0b6b3a7640000808204905090506109c052610ac05160206151ae6000396000518082028215828483041417156151495790509050610ac052610ae051610b00518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610ae05260006002905b80610b205260006020610b2051600281101561514957026004013511156108de576323b872dd610b405233610b605230610b80526020610b20516002811015615149570260040135610ba0526020610b406064610b5c60006020610b20516002811015615149570261096001515af161086f573d600060003e3d6000fd5b60203d1061514957610b40518060011c61514957610bc052610bc05115615149576020610b2051600281101561514957026109a001516020610b205160028110156151495702610ac0015180821061514957808203905090506020610b2051600281101561514957026109e001525b6001018181186107f15750506000600435116108ff57600060243511610902565b60015b1561514957600854610b20526000610b20511161092557601954610aa052610968565b61092051610160526109405161018052610ac0516101a052610ae0516101c052610950610b4061234d565b610b4051610aa052610b205142106109685760016008555b610920516101605261094051610180526109a0516101a0526109c0516101c052610993610b6061234d565b610b6051610b40526318160ddd610b80526020610b806004610b9c602061514e6000396000515afa6109ca573d600060003e3d6000fd5b60203d1061514957610b8051610b60526000610aa05111610a0557610b4051610160526109f8610b806134f9565b610b8051610a6052610a49565b610b6051610b40518082028215828483041417156151495790509050610aa05180801561514957820490509050610b60518082106151495780820390509050610a60525b6000610a60511115615149576000610aa05111610ae157610b4051601955670de0b6b3a7640000601e55670de0b6b3a7640000601c556340c10f19610b805261090051610ba052610a6051610bc0526020610b806044610b9c6000602061514e6000396000515af1610ac0573d600060003e3d6000fd5b60203d1061514957610b80518060011c61514957610be052610be050610de9565b6109e05160c052610a005160e0526109a051610100526109c05161012052610b0a610b806149f0565b610b8051610a605180820282158284830414171561514957905090506402540be40080820490509050600181818301106151495780820190509050610a8052610a6051610a80518082106151495780820390509050610a6052610b6051610a605181818301106151495780820190509050610b60526340c10f19610b805261090051610ba052610a6051610bc0526020610b806044610b9c6000602061514e6000396000515af1610bc0573d600060003e3d6000fd5b60203d1061514957610b80518060011c61514957610be052610be0506000610b8052620186a0610a60511115610db15760043515610c015760243515610c04565b60015b15610db157606036610ba03760043515610c5357610a405160206151ce6000396000518082028215828483041417156151495790509050610ba05260206151ae600039600051610bc052610c90565b610a205160206151ae6000396000518082028215828483041417156151495790509050610ba05260206151ce600039600051610bc0526001610be0525b610ba051610a60518082028215828483041417156151495790509050610b605180801561514957820490509050610ba052610ba051670de0b6b3a764000080820282158284830414171561514957905090506020610be0516002811015615149570260040135610bc0518082028215828483041417156151495790509050610a60516020610be05160028110156151495702610a2001518082028215828483041417156151495790509050610bc0518082028215828483041417156151495790509050610b605180801561514957820490509050808210615149578082039050905080801561514957820490509050610b8052610be051610db1576ec097ce7bc90715b34b9f1000000000610b805180801561514957820490509050610b80525b610920516106005261094051610620526109a051610640526109c05161066052610b805161068052610b40516106a052610de961398d565b604435610a60511015610e5c576008610b80527f536c697070616765000000000000000000000000000000000000000000000000610ba052610b8050610b805180610ba00181600003601f1636823750506308c379a0610b40526020610b6052601f19601f610b80510116604401610b5cfd5b610900517f540ab385f9b5d450a27404172caade516b3ba3f4be88239ac56a2ad1de2a1f5a600435610b8052602435610ba052610a8051610bc052610b6051610be0526080610b80a26020610a606000600055f35b635b36389c8118610ec55733604052610edf565b633eb1719f8118611182576064358060a01c615149576040525b600054615149576001600055602061516e600039600051606052602061518e6000396000516080526318160ddd60c052602060c0600460dc602061514e6000396000515afa610f33573d600060003e3d6000fd5b60203d106151495760c05160a0526379cc679060c0523360e05260043561010052602060c0604460dc6000602061514e6000396000515af1610f7a573d600060003e3d6000fd5b60203d106151495760c0518060011c61514957610120526101205060175460c05260185460e052600435600180821061514957808203905090506101005260006002905b80610120526020610120516002811015615149570260c0015161010051808202821582848304141715615149579050905060a051808015615149578204905090506101405260206101205160028110156151495702602401356101405110615149576020610120516002811015615149570260c001516101405180821061514957808203905090506101205160028110156151495760170155610140516020610120516002811015615149570260c0015263a9059cbb6101605260405161018052610140516101a0526020610160604461017c600060206101205160028110156151495702606001515af16110b8573d600060003e3d6000fd5b60203d1061514957610160518060011c615149576101c0526101c0511561514957600101818118610fbe57505060195461012052610120516101205161010051808202821582848304141715615149579050905060a051808015615149578204905090508082106151495780820390509050601955337fdd3c0336a16f1b64f172b7bb0dad5b2b3c7c76f91e8c4aafd6aae60dce80015360c0516101405260e0516101605260a0516004358082106151495780820390509050610180526060610140a26000600055005b638d8ea72781186113f8576318160ddd610420526020610420600461043c602061514e6000396000515afa6111bc573d600060003e3d6000fd5b60203d1061514957610420516104005260015460206151ce6000396000518082028215828483041417156151495790509050610420526111fd610480613290565b6104808051610440526020810151610460525061121b6104c0613221565b6104c080516104805260208101516104a0525060043560206151ae60003960005180820282158284830414171561514957905090506104c052602435610420518082028215828483041417156151495790509050670de0b6b3a7640000808204905090506104e05260195461050052600060085411156112c95761044051610160526104605161018052610480516101a0526104a0516101c0526112c061052061234d565b61052051610500525b610480516104c05181818301106151495780820190509050610480526104a0516104e051818183011061514957808201905090506104a05261044051610160526104605161018052610480516101a0526104a0516101c05261132c61054061234d565b610540516105205261040051610520518082028215828483041417156151495790509050610500518080156151495782049050905061040051808210615149578082039050905061054052610540516104c05160c0526104e05160e05261048051610100526104a051610120526113a46105606149f0565b610560516105405180820282158284830414171561514957905090506402540be400808204905090506001818183011061514957808201905090508082106151495780820390509050610540526020610540f35b634fb08c5e81186114775760206114106106a0613290565b6106a080516107805260208101516107a05250604060046107c03760016108005260006108205261078051610400526107a051610420526107c051610440526107e051610460526108005161048052610820516104a0526114726106e0614b5a565b6106e0f35b63f1dc3cc9811861148c5733610900526114a7565b630fbcee6e8118611751576064358060a01c61514957610900525b600054615149576001600055602054615149576114c5610960613290565b6109608051610920526020810151610940525060a03661096037600854610a00526109205161040052610940516104205260406004610440376000610a0051116104805260016104a05261151a610a20614b5a565b610a2080516109605260208101516109a0526040810151610980526060810180516109c05260208101516109e05250506044356109605110156115bd576008610a20527f536c697070616765000000000000000000000000000000000000000000000000610a4052610a2050610a205180610a400181600003601f1636823750506308c379a06109e0526020610a0052601f19601f610a205101166044016109fcfd5b610a005142106115cd5760016008555b60243560028110156151495760170180546109605180821061514957808203905090508155506379cc6790610a205233610a4052600435610a60526020610a206044610a3c6000602061514e6000396000515af1611630573d600060003e3d6000fd5b60203d1061514957610a20518060011c61514957610a8052610a8050602061516e600039600051610a2052602061518e600039600051610a405263a9059cbb610a605261090051610a805261096051610aa0526020610a606044610a7c6000602060243560028110156151495702610a2001515af16116b4573d600060003e3d6000fd5b60203d1061514957610a60518060011c61514957610ac052610ac0511561514957610920516106005261094051610620526109c051610640526109e051610660526109a05161068052610980516106a05261170d61398d565b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a060406004610a603761096051610aa0526060610a60a260206109606000600055f35b63c93f49e8811861177757600054615149576001600055611770613576565b6000600055005b635e248072811861196e57601a543318615149576007546201517f8181830110615149578082019050905042111561514957426201517f818183011061514957808201905090506044351115615149576117d2610160613290565b610160805161012052602081015161014052506101205160801b6101605261014051610160511761016052610f9f60043511156151495763ee6b28016004351015615149576402540be3ff60243511156151495766470de4df820001602435101561514957670de0b6b3a76400006004358082028215828483041417156151495790509050610120518080156151495782049050905061018052678ac7230489e800016101805110156151495767016345785d89ffff61018051111561514957670de0b6b3a76400006024358082028215828483041417156151495790509050610140518080156151495782049050905061018052678ac7230489e800016101805110156151495767016345785d89ffff61018051111561514957610160516005554260075560043560801b6101a0526024356101a051176101a0526044356008556101a0516006557fe35f0559b0642164e286b30df2077ec3a05426617a25db7578fd20ba39a6cd05610120516101c0526004356101e05261014051610200526024356102205242610240526044356102605260c06101c0a1005b63244c7c2e8118611a0c57601a5433186151495761198d610160613290565b610160805161012052602081015161014052506101205160801b6101605261014051610160511761016052610160516005556101605160065542600755426008557f5f0e7fba3d100c9e19446e1c92fe436f0a9a22fe99669360e4fdd6d3de2fc2846101205161018052610140516101a052426101c0526060610180a1005b63a43c33518118611bb657601a543318615149576023546151495760e060046040376402540be40160605110611a4757601254606052611a55565b6207a11f6060511115615149575b6402540be4006040511115611a6b576011546040525b60605160405111615149576402540be4006080511115611a8c576013546080525b670de0b6b3a764000060a05110611aa857600b5460a052611ab4565b600060a0511115615149575b670de0b6b3a764000060c0511115611acd5760095460c0525b670de0b6b3a764000060e0511115611ae657600d5460e0525b62093a806101005110611aff57600f5461010052611b0c565b6000610100511115615149575b426203f48081818301106151495780820190509050610120526101205160235560805160165560405160145560605160155560a051600c5560c051600a5560e051600e5561010051601055610120517f913fde9a37e1f8ab67876a4d0ce80790d764fcfc5692f4529526df9c6bdde55360805161014052604051610160526060516101805260a0516101a05260c0516101c05260e0516101e052610100516102005260e0610140a2005b632a7dd7cd8118611ccb57600054615149576001600055601a54331861514957602354421061514957600060235414615149576000602355601654610600526106005160135414611c1157611c09613576565b610600516013555b60145461062052610620516011556015546106405261064051601255600c546106605261066051600b55600a546106805261068051600955600e546106a0526106a051600d556010546106c0526106c051600f557f1c65bbdc939f346e5d6f0bde1f072819947438d4fc7b182cc59c2f6dc5504087610600516106e05261062051610700526106405161072052610660516107405261068051610760526106a051610780526106c0516107a05260e06106e0a16000600055005b63226840fb8118611ce657601a543318615149576000602355005b636b441a408118611d61576004358060a01c61514957604052601a5433186151495760225461514957426203f48081818301106151495780820190509050606052606051602255604051601b556040516060517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb93560006080a3005b636a1c05ae8118611dc457601a54331861514957602254421061514957600060225414615149576000602255601b54604052604051601a556040517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c60006060a2005b6386fbf1938118611ddf57601a543318615149576000602255005b63e36988538118611e0457601a54331861514957426021541115615149576001602055005b633046f9728118611e1f57601a543318615149576000602055005b637242e5248118611e49576004358060a01c61514957604052601a54331861514957604051602455005b6354f0f7d58118611ec5576002601e548082028215828483041417156151495790509050611e786102406138ac565b610240516102805261028051604052611e92610260615027565b610260518082028215828483041417156151495790509050670de0b6b3a7640000808204905090506102a05260206102a0f35b63b9e8c9fd8118611edc5760015460405260206040f35b63c146bf948118611ef35760035460405260206040f35b636112c7478118611f0a5760045460405260206040f35b63204fe3d58118611f215760055460405260206040f35b63f30cfad58118611f385760065460405260206040f35b63e89876ff8118611f4f5760075460405260206040f35b63f9ed95978118611f665760085460405260206040f35b6349fe9e778118611f7d5760095460405260206040f35b63727ced578118611f9457600a5460405260206040f35b6372d4f0e28118611fab57600b5460405260206040f35b63d7c3dcbe8118611fc257600c5460405260206040f35b63083812e58118611fd957600d5460405260206040f35b634ea12c7d8118611ff057600e5460405260206040f35b63662b6274811861200757600f5460405260206040f35b630c5e23d4811861201e5760105460405260206040f35b6392526c0c81186120355760115460405260206040f35b63ee8de675811861204c5760125460405260206040f35b63fee3f7f981186120635760135460405260206040f35b637cf9aedc811861207a5760145460405260206040f35b637d1b060c81186120915760155460405260206040f35b63e382446281186120a85760165460405260206040f35b634903b0d181186120cc576004356002811015615149576017015460405260206040f35b630f529ba281186120e35760195460405260206040f35b638da5cb5b81186120fa57601a5460405260206040f35b631ec0cdc1811861211157601b5460405260206040f35b637ba1a74d811861212857601c5460405260206040f35b630b7b594b811861213f57601d5460405260206040f35b630c46b72a811861215657601e5460405260206040f35b639c868ac0811861216d5760205460405260206040f35b632a42689681186121845760215460405260206040f35b63e0a0b586811861219b5760225460405260206040f35b63405e28f881186121b25760235460405260206040f35b636e42e4d281186121c95760245460405260206040f35b505b60006000fd5b60405160a05260605160c0526080516121eb5760006121f3565b60c05160a051105b156122055760605160a05260405160c0525b60a05160e052600061010052600060ff905b806101205260e05161014052600260e05160a05160c051808202821582848304141715615149579050905060e05180801561514957820490509050818183011061514957808201905090500460e0526101405160e051116122835760e051610140510361010052612290565b6101405160e05103610100525b60016101005111156122c65760e05161010051670de0b6b3a76400008082028215828483041417156151495790509050106122c9565b60015b156122db5760e051835250505061234b565b6001018181186122175750506010610120527f446964206e6f7420636f6e766572676500000000000000000000000000000000610140526101205061012051806101400181600003601f1636823750506308c379a060e052602061010052601f19601f61012051011660440160fcfd5b565b610f9f610160511161236057600061236b565b63ee6b280161016051105b15615149576402540be3ff6101805111612386576000612394565b66470de4df82000161018051105b15615149576101a0516101e0526101c05161020052610200516101e05110156123c8576101c0516101e0526101a051610200525b633b9ac9ff6101e051116123dd5760006123f2565b6d314dc6448d9338c15b0a000000016101e051105b1561514957655af3107a3fff61020051670de0b6b3a764000080820282158284830414171561514957905090506101e0518080156151495782049050905011156151495760026101e0516040526102005160605260006080526124566102406121d1565b610240518082028215828483041417156151495790509050610220526101e05161020051818183011061514957808201905090506102405261018051670de0b6b3a76400008181830110615149578082019050905061026052600060ff905b8061028052610220516102a0526000610220511115615149576102205161022051673782dace9d9000006101e051808202821582848304141715615149579050905004610200518082028215828483041417156151495790509050046102c052610260516102e0526102c0516102e0511161254e576102e0516102c051036001818183011061514957808201905090506102e05261256e565b6102c0516102e051036001818183011061514957808201905090506102e0525b610160516101805161018051670de0b6b3a7640000610220518082028215828483041417156151495790509050046102e0518082028215828483041417156151495790509050046102e0518082028215828483041417156151495790509050612710808202821582848304141715615149579050905004610300526102e051673782dace9d9000006102c0518082028215828483041417156151495790509050046103205261024051670de0b6b3a764000061024051610320518082028215828483041417156151495790509050048181830110615149578082019050905061030051600280820282158284830414171561514957905090506102c0518080156151495782049050905081818301106151495780820190509050670de0b6b3a76400006103205161022051808202821582848304141715615149579050905004808210615149578082039050905061034052610220516103405161024051818183011061514957808201905090508082028215828483041417156151495790509050610340518080156151495782049050905061036052610220516102205180820282158284830414171561514957905090506103405180801561514957820490509050610380526102c051670de0b6b3a7640000116127cd5761038051670de0b6b3a764000061022051610300516103405180801561514957820490509050808202821582848304141715615149579050905004670de0b6b3a76400006102c0510380820282158284830414171561514957905090506102c05180801561514957820490509050808210615149578082039050905061038052612850565b61038051670de0b6b3a7640000610220516103005161034051808015615149578204905090508082028215828483041417156151495790509050046102c051670de0b6b3a76400000380820282158284830414171561514957905090506102c0518080156151495782049050905081818301106151495780820190509050610380525b6103805161036051116128725760026103605161038051030461022052612880565b610380516103605103610220525b60006103a0526102a05161022051116128a557610220516102a051036103a0526128b3565b6102a05161022051036103a0525b6102205180662386f26fc10000811882662386f26fc1000011021890506103a051655af3107a4000808202821582848304141715615149579050905010156129855760006002905b602081026101e001516103c0526103c051670de0b6b3a7640000808202821582848304141715615149579050905061022051808015615149578204905090506103e052662386f26fc0ffff6103e05111612956576000612966565b68056bc75e2d631000016103e051105b15615149576001018181186128fb5750506102205183525050506129f7565b6001018181186124b55750506010610280527f446964206e6f7420636f6e7665726765000000000000000000000000000000006102a0526102805061028051806102a00181600003601f1636823750506308c379a061024052602061026052601f19601f61028051011660440161025cfd5b565b610f9f60405111612a0b576000612a15565b63ee6b2801604051105b15615149576402540be3ff60605111612a2f576000612a3c565b66470de4df820001606051105b156151495767016345785d89ffff60c05111612a59576000612a6d565b6d314dc6448d9338c15b0a0000000160c051105b15615149576020600160e051808210615149578082039050905060028110156151495702608001516101005270010000000000000000000000000000000060c051101561514957600260c0510a61010051600480820282158284830414171561514957905090508080156151495782049050905061012052671bc16d674ec8000061010051808202821582848304141715615149579050905060c051808015615149578204905090506101405266470de4df81ffff6101405111612b32576000612b42565b680ad78ebc5ac620000161014051105b156151495761010051655af3107a40008082049050905060c051655af3107a400080820490509050808281188284110218905090506064818118606483110218905061016052606051670de0b6b3a76400008181830110615149578082019050905061018052600060ff905b806101a052610120516101c05260c0516101405161012051808202821582848304141715615149579050905060028082028215828483041417156151495790509050046101e0526101005161012051818183011061514957808201905090506102005261018051610220526101e0516102205111612c4a57610220516101e0510360018181830110615149578082019050905061022052612c6a565b6101e0516102205103600181818301106151495780820190509050610220525b604051606051606051670de0b6b3a764000060c051808202821582848304141715615149579050905004610220518082028215828483041417156151495790509050046102205180820282158284830414171561514957905090506127108082028215828483041417156151495790509050046102405261022051670de0b6b3a7640000671bc16d674ec800006101e0518082028215828483041417156151495790509050818183011061514957808201905090500461026052670de0b6b3a7640000610120518082028215828483041417156151495790509050610200516102605180820282158284830414171561514957905090508181830110615149578082019050905061024051818183011061514957808201905090506102805260c0516102605180820282158284830414171561514957905090506102a0526102a0516102805110612dc7576102a051610280510361028052612dd7565b60026101c0510461012052612fc7565b6102805161012051808015615149578204905090506102c052610240516102c051808015615149578204905090506102e05261028051670de0b6b3a764000060c0518082028215828483041417156151495790509050818183011061514957808201905090506102c051808015615149578204905090506102e051670de0b6b3a764000080820282158284830414171561514957905090506101e0518080156151495782049050905081818301106151495780820190509050610300526102e051670de0b6b3a76400006102005180820282158284830414171561514957905090506102c05180801561514957820490509050818183011061514957808201905090506102e0526102e0516103005110612efd576102e051610300510361012052612f09565b60026101c05104610120525b6000610320526101c0516101205111612f2e57610120516101c0510361032052612f3c565b6101c0516101205103610320525b61016051655af3107a4000610120510480828118828411021890509050610320511015612fc75760c05161012051670de0b6b3a764000080820282158284830414171561514957905090500461034052662386f26fc0ffff6103405111612fa4576000612fb4565b68056bc75e2d6310000161034051105b1561514957610120518352505050613039565b600101818118612bae57505060106101a0527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101c0526101a0506101a051806101c00181600003601f1636823750506308c379a061016052602061018052601f19601f6101a051011660440161017cfd5b565b670de0b6b3a764000060405104606052603b606051111561306057600081525061321f565b670de0b6b3a7640000606051026040510360805260605160020a60a05260a051670de0b6b3a76400000460a05260805161309f5760a05181525061321f565b670de0b6b3a764000060c052670de0b6b3a764000060e052600061010052600160ff8101905b8061012052670de0b6b3a7640000610120510261014052670de0b6b3a7640000610140510361016052610160516080511161310b57608051610160510361016052613121565b6101605160805103610160526101005115610100525b610140516002610160510460c051020460c0526101005161315a5760e05160c0518181830110615149578082019050905060e052613172565b60e05160c051808210615149578082039050905060e0525b6402540be40060c05110156131af57670de0b6b3a764000060a05160e051808202821582848304141715615149579050905004835250505061321f565b6001018181186130c55750506010610120527f446964206e6f7420636f6e766572676500000000000000000000000000000000610140526101205061012051806101400181600003601f1636823750506308c379a060e052602061010052601f19601f61012051011660440160fcfd5b565b60175460206151ae60003960005180820282158284830414171561514957905090508152670de0b6b3a764000060185460206151ce6000396000518082028215828483041417156151495790509050600154808202821582848304141715615149579050905004602082015250565b6008546040526006546060526fffffffffffffffffffffffffffffffff6060511660805260605160801c60a0526040514210156133dd5760055460c05260075460e05260405160e05180821061514957808203905090506040524260e051808210615149578082039050905060e05260405160e05180821061514957808203905090506101005260c05160801c61010051808202821582848304141715615149579050905060a05160e0518082028215828483041417156151495790509050818183011061514957808201905090506040518080156151495782049050905060a0526fffffffffffffffffffffffffffffffff60c0511661010051808202821582848304141715615149579050905060805160e051808202821582848304141715615149579050905081818301106151495780820190509050604051808015615149578204905090506080525b60a0518152608051602082015250565b600b546080526040516060518181830110615149578082019050905060a052670de0b6b3a764000060805102670de0b6b3a76400006080510160a051673782dace9d900000604051808202821582848304141715615149579050905060a0518080156151495782049050905060605180820282158284830414171561514957905090500480821061514957808203905090508080156151495782049050905060a052670de0b6b3a764000060115460a0518082028215828483041417156151495790509050601254670de0b6b3a764000060a051808210615149578082039050905080820282158284830414171561514957905090508181830110615149578082019050905004815250565b600261016051046101805261016051670de0b6b3a7640000808202821582848304141715615149579050905060015460028082028215828483041417156151495790509050808015615149578204905090506101a052610180516040526101a051606052600160805261356d6101c06121d1565b6101c051815250565b613581610440613290565b61044080516104005260208101516104205250601c5461044052601d5461046052602061516e60003960005161048052602061518e6000396000516104a05260006002905b806104c0526370a082316104e052306105005260206104e060246104fc60206104c0516002811015615149570261048001515afa613609573d600060003e3d6000fd5b60203d10615149576104e0516104c051600281101561514957601701556001018181186135c6575050601e546104c052610460516104405111156137a5576404a817c800610440516104605180821061514957808203905090506013548082028215828483041417156151495790509050046104e05260006104e05111156137a55760245461050052600061050051146137a5576104c051670de0b6b3a764000080820282158284830414171561514957905090506104c0516104e051808210615149578082039050905080801561514957820490509050670de0b6b3a7640000808210615149578082039050905061052052636962f845610560526105005161058052610520516105a0526020610560604461057c6000602061514e6000396000515af161373d573d600060003e3d6000fd5b60203d106151495761056051610540526104405160026104e0510280821061514957808203905090506104405261044051601c55610500517f6059a38198b1dc42b3791087d1ff0fbd72b3179553c25f678cd246f52ffaaf5961054051610560526020610560a25b6318160ddd610500526020610500600461051c602061514e6000396000515afa6137d4573d600060003e3d6000fd5b60203d1061514957610500516104e0526104005161058052610420516105a0526137ff610520613221565b61052080516105c05260208101516105e0525061058051610160526105a051610180526105c0516101a0526105e0516101c05261383d61056061234d565b610560516105005261050051601955670de0b6b3a764000061050051610160526138686105206134f9565b6105205180820282158284830414171561514957905090506104e05180801561514957820490509050601e55610460516104405111156138aa5761044051601d555b565b600254610180526004546101a052426101a051106138d4576101805181525061398b5661398b565b600f546101c0526003546101e0526101c051670de0b6b3a7640000426101a0518082106151495780820390509050020460405261391261022061303b565b6102205161020052670de0b6b3a76400006101e051670de0b6b3a7640000610200518082106151495780820390509050808202821582848304141715615149579050905061018051610200518082028215828483041417156151495790509050818183011061514957808201905090500481525061398b565b565b6002546106c0526003546106e052600154610700526004546107205260006107405242610720511015613a7257600f546107605261076051670de0b6b3a76400004261072051808210615149578082039050905002046040526139f16107a061303b565b6107a05161078052670de0b6b3a76400006106e051670de0b6b3a764000061078051808210615149578082039050905080820282158284830414171561514957905090506106c05161078051808202821582848304141715615149579050905081818301106151495780820190509050046106c0526106c051600255426004555b6106a051610760526106a051613ab65761060051610160526106205161018052610640516101a052610660516101c052613aad61078061234d565b61078051610760525b60006106805111613b75576106405161078052610660516107a052620f424061078051046107c052610780516107c0518181830110615149578082019050905061078052610700516107c0518082028215828483041417156151495790509050610660516106005160405261062051606052610780516080526107a05160a0526107605160c052600160e052613b4d6107e06129f9565b6107e0518082106151495780820390509050808015615149578204905090506106e052613b7e565b610680516106e0525b6106e0516003556318160ddd6107a05260206107a060046107bc602061514e6000396000515afa613bb4573d600060003e3d6000fd5b60203d10615149576107a05161078052601c546107a052601e546107c052600261076051046107e05261076051670de0b6b3a7640000808202821582848304141715615149579050905060026107005180820282158284830414171561514957905090508080156151495782049050905061080052670de0b6b3a764000061082052670de0b6b3a76400006108405260006107c0511115613d79576107e051604052610800516060526001608052613c6d6108806121d1565b6108805161086052670de0b6b3a76400006108605180820282158284830414171561514957905090506107805180801561514957820490509050610840526107a0516108405180820282158284830414171561514957905090506107c0518080156151495782049050905061082052600854610880526107c0516108405110613cf7576000613cfd565b61088051155b15613d685760046108a0527f4c6f7373000000000000000000000000000000000000000000000000000000006108c0526108a0506108a051806108c00181600003601f1636823750506308c379a061086052602061088052601f19601f6108a051011660440161087cfd5b60016108805118613d795760006008555b61082051601c556106c051670de0b6b3a76400008082028215828483041417156151495790509050610700518080156151495782049050905061086052670de0b6b3a76400006108605111613ddf5761086051670de0b6b3a76400000361086052613df2565b670de0b6b3a76400006108605103610860525b600d54600a61086051048082811882841102189050905061088052601f546108a0526108a05115613e24576000613e97565b61082051600260095402818183011061514957808201905090506108405160028082028215828483041417156151495790509050670de0b6b3a7640000808210615149578082039050905011613e7b576000613e97565b610880516108605111613e8f576000613e97565b60006107c051115b15613ea85760016108a0526001601f555b6108a051156140dd57610880516108605111613ec5576000613ecd565b60006107c051115b156140dd576108605161070051610860516108805180821061514957808203905090508082028215828483041417156151495790509050610880516106c0518082028215828483041417156151495790509050818183011061514957808201905090500461074052610640516107e05261066051610740518082028215828483041417156151495790509050610700518080156151495782049050905061080052610600516101605261062051610180526107e0516101a052610800516101c052613f996108e061234d565b6108e0516108c05260026108c051046107e0526108c051670de0b6b3a7640000808202821582848304141715615149579050905060026107405180820282158284830414171561514957905090508080156151495782049050905061080052670de0b6b3a76400006107e05160405261080051606052600160805261401f6108e06121d1565b6108e051808202821582848304141715615149579050905061078051808015615149578204905090506107c052670de0b6b3a76400006107c0511161406557600061409c565b6108205160026107c0518082028215828483041417156151495790509050670de0b6b3a76400008082106151495780820390509050115b6140c3576000601f556107605160195561084051601e5561410161357656614101566140dd565b610740516001556108c0516019556107c051601e55614101565b6107605160195561084051601e556108a05115614101576000601f55614101613576565b565b6020546151495761094051610920511461514957600261092051101561514957600261094051101561514957600061096051111561514957614146610a60613290565b610a608051610a20526020810151610a405250601754610a6052601854610a8052604036610aa037602061516e600039600051610ae052602061518e600039600051610b005260206109405160028110156151495702610a600151610b205260206109205160028110156151495702610a600151610b4052610b4051610960518181830110615149578082019050905060206109205160028110156151495702610a60015260206109205160028110156151495702610a6001516109205160028110156151495760170155600154610b6052610a605160206151ae6000396000518082028215828483041417156151495790509050610a6052610a8051610b6051808202821582848304141715615149579050905060206151ce6000396000518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610a805260206151ae600039600051610b805260206151ce600039600051610ba052600161092051186142d65760206151ce600039600051610b805260206151ae600039600051610ba0525b600854610bc0526000610bc05111156143d357610b4051610b80518082028215828483041417156151495790509050610b4052600061092051111561434657610b4051610b60518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610b40525b60206109205160028110156151495702610a600151610be052610b405160206109205160028110156151495702610a600152610a205161016052610a405161018052610a60516101a052610a80516101c0526143a3610c0061234d565b610c0051601955610be05160206109205160028110156151495702610a600152610bc05142106143d35760016008555b60206109405160028110156151495702610a600151610a2051604052610a4051606052610a6051608052610a805160a05260195460c0526109405160e05261441c610be06129f9565b610be0518082106151495780820390509050610ac05260206109405160028110156151495702610a60018051610ac0518082106151495780820390509050815250610ac05160018082106151495780820390509050610ac05260006109405111156144b857610ac051670de0b6b3a76400008082028215828483041417156151495790509050610b605180801561514957820490509050610ac0525b610ac051610ba05180801561514957820490509050610ac052610ac051610a6051604052610a80516060526144ee610be06133ed565b610be051610ac05180820282158284830414171561514957905090506402540be400808204905090508082106151495780820390509050610ac05261098051610ac051101561459d576008610be0527f536c697070616765000000000000000000000000000000000000000000000000610c0052610be050610be05180610c000181600003601f1636823750506308c379a0610ba0526020610bc052601f19601f610be0510116604401610bbcfd5b610b2051610ac0518082106151495780820390509050610b2052610b205161094051600281101561514957601701556004610c20526000610c4052610c208051602082012090506109e051610a002018614667576323b872dd610c605261090051610c805230610ca05261096051610cc0526020610c606064610c7c600060206109205160028110156151495702610ae001515af1614641573d600060003e3d6000fd5b60203d1061514957610c60518060011c61514957610ce052610ce05115615149576147a6565b60206109205160028110156151495702610ae00151610be0526370a08231610c205230610c40526020610c206024610c3c610be0515afa6146ad573d600060003e3d6000fd5b60203d1061514957610c2051610c005260006109e05181610c4001610a00518152508082019150506109005181610c4001526020810190506109a05181610c400152602081019050610be05181610c4001526020810190506109605181610c400152602081019050610ac05181610c40015260208101905080610c2052610c20505060006000610c2051610c4060006109c0515af1614751573d600060003e3d6000fd5b610960516370a08231610c205230610c40526020610c206024610c3c610be0515afa614782573d600060003e3d6000fd5b60203d1061514957610c2051610c0051808210615149578082039050905018615149575b63a9059cbb610be0526109a051610c0052610ac051610c20526020610be06044610bfc600060206109405160028110156151495702610ae001515af16147f1573d600060003e3d6000fd5b60203d1061514957610be0518060011c61514957610c4052610c40511561514957610b2051610ba0518082028215828483041417156151495790509050610b2052600061094051111561486f57610b2051610b60518082028215828483041417156151495790509050670de0b6b3a764000080820490509050610b20525b610b205160206109405160028110156151495702610a600152620186a0610960511161489c5760006148a6565b620186a0610ac051115b156149665761096051610b80518082028215828483041417156151495790509050610be052610ac051610ba0518082028215828483041417156151495790509050610c0052610920511561492f57610c0051670de0b6b3a76400008082028215828483041417156151495790509050610be05180801561514957820490509050610aa052614966565b610be051670de0b6b3a76400008082028215828483041417156151495790509050610c005180801561514957820490509050610aa0525b610a205161060052610a405161062052610a605161064052610a805161066052610aa0516106805260006106a05261499c61398d565b610900517fb2e76ae99761dc136e598d4a629bb347eccb9532a5f8bbd72e18467c3c34cc9861092051610be05261096051610c005261094051610c2052610ac051610c40526080610be0a2610ac051815250565b6101005160405261012051606052614a096101606133ed565b61016051600280820282158284830414171561514957905090506004808204905090506101405260006101605260006002905b6020810260c001516101805261016051610180518181830110615149578082019050905061016052600101818118614a3c575050610160516002808204905090506101805260006101a05260006002905b6020810260c001516101c052610180516101c05111614ad9576101a051610180516101c0518082106151495780820390509050818183011061514957808201905090506101a052614b08565b6101a0516101c051610180518082106151495780820390509050818183011061514957808201905090506101a0525b600101818118614a8d575050610140516101a05180820282158284830414171561514957905090506101605180801561514957820490509050620186a081818301106151495780820190509050815250565b6318160ddd6104e05260206104e060046104fc602061514e6000396000515afa614b89573d600060003e3d6000fd5b60203d10615149576104e0516104c0526104c0516104405111615149576002610460511015615149576017546104e0526018546105005260006105205260015460206151ce6000396000518082028215828483041417156151495790509050610540526104e05160206151ae60003960005180820282158284830414171561514957905090506105605261050051610540518082028215828483041417156151495790509050670de0b6b3a7640000808204905090506105805261046051614c7857670de0b6b3a764000060206151ae6000396000518082028215828483041417156151495790509050610540525b61048051614c8c5760195461052052614cc0565b61040051610160526104205161018052610560516101a052610580516101c052614cb76105a061234d565b6105a051610520525b610520516105a0526105605160405261058051606052614ce16105e06133ed565b6105e0516105c052610440516105a05180820282158284830414171561514957905090506104c051808015615149578204905090506105e0526105a0516105e0516105c0516105e05180820282158284830414171561514957905090506404a817c80080820490509050600181818301106151495780820190509050808210615149578082039050905080821061514957808203905090506105a0526104005160405261042051606052610560516080526105805160a0526105a05160c0526104605160e052614db26106206129f9565b6106205161060052602061046051600281101561514957026105600151610600518082106151495780820390509050670de0b6b3a76400008082028215828483041417156151495790509050610540518080156151495782049050905061062052610600516020610460516002811015615149570261056001526000610640526104a051614e41576000614e5f565b620186a06106205111614e55576000614e5f565b620186a061044051115b15614ff85760006106605260206151ae6000396000516106805260016104605118614ebf576104e05160206151ae60003960005180820282158284830414171561514957905090506106605260206151ce60003960005161068052614ee7565b6105005160206151ce6000396000518082028215828483041417156151495790509050610660525b610660516105e051808202821582848304141715615149579050905061052051808015615149578204905090506106605261066051670de0b6b3a76400008082028215828483041417156151495790509050610620516106805180820282158284830414171561514957905090506105e051602061046051600281101561514957026104e00151808202821582848304141715615149579050905061068051808202821582848304141715615149579050905061052051808015615149578204905090508082106151495780820390509050808015615149578204905090506106405261046051614ff8576ec097ce7bc90715b34b9f10000000006106405180801561514957820490509050610640525b6106205181526106405160208201526105a0516040820152606081016105605181526105805160208201525050565b604051615038576000815250615147565b604051670de0b6b3a7640000818183011061514957808201905090506002808204905090506060526040516080526000610100905b8060a05260805160605118615089576080518352505050615147565b606051608052604051670de0b6b3a76400008082028215828483041417156151495790509050606051808015615149578204905090506060518181830110615149578082019050905060028082049050905060605260010181811861506d575050601060a0527f446964206e6f7420636f6e76657267650000000000000000000000000000000060c05260a05060a0518060c00181600003601f1636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b565b600080fd0000000000000000000000000ca1c1ec4ebf3cc67a9f545ff90a3795b318ca4a000000000000000000000000cb444e90d8198415266c6a2724b7900fb12fc56e0000000000000000000000001337bedc9d22ecbe766df105c9623922a27963ec00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000cbaf0a32f5a16b326f00607421857f68fc72e5080000000000000000000000006f8eef407b974dff82c53ff939cc1ebb699383fb000000000000000000000000000000000000000000000000000000000bebc20000000000000000000000000000000000000000000000000000005af3107a400000000000000000000000000000000000000000000000000000000000004c4b400000000000000000000000000000000000000000000000000000000002aea54000000000000000000000000000000000000000000000000000000002540be4000000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000000000500918bd800000000000000000000000000000000000000000000000000000000012a05f20000000000000000000000000000000000000000000000000000000000000004b00000000000000000000000000000000000000000000000000d3e9777fd1e28800000000000000000000000000ca1c1ec4ebf3cc67a9f545ff90a3795b318ca4a000000000000000000000000cb444e90d8198415266c6a2724b7900fb12fc56e0000000000000000000000001337bedc9d22ecbe766df105c9623922a27963ec

-----Decoded View---------------
Arg [0] : owner (address): 0xCBAf0A32F5a16B326F00607421857F68FC72e508
Arg [1] : admin_fee_receiver (address): 0x6f8EEF407B974DFF82c53FF939CC1EBb699383fB
Arg [2] : A (uint256): 200000000
Arg [3] : gamma (uint256): 100000000000000
Arg [4] : mid_fee (uint256): 5000000
Arg [5] : out_fee (uint256): 45000000
Arg [6] : allowed_extra_profit (uint256): 10000000000
Arg [7] : fee_gamma (uint256): 5000000000000000
Arg [8] : adjustment_step (uint256): 5500000000000
Arg [9] : admin_fee (uint256): 5000000000
Arg [10] : ma_half_time (uint256): 1200
Arg [11] : initial_price (uint256): 954366712652638336
Arg [12] : _token (address): 0x0CA1C1eC4EBf3CC67a9f545fF90a3795b318cA4a
Arg [13] : _coins (address[2]): 0xcB444e90D8198415266c6a2724b7900fb12FC56E,0x1337BedC9D22ecbe766dF105c9623922A27963EC

-----Encoded View---------------
15 Constructor Arguments found :
Arg [0] : 000000000000000000000000cbaf0a32f5a16b326f00607421857f68fc72e508
Arg [1] : 0000000000000000000000006f8eef407b974dff82c53ff939cc1ebb699383fb
Arg [2] : 000000000000000000000000000000000000000000000000000000000bebc200
Arg [3] : 00000000000000000000000000000000000000000000000000005af3107a4000
Arg [4] : 00000000000000000000000000000000000000000000000000000000004c4b40
Arg [5] : 0000000000000000000000000000000000000000000000000000000002aea540
Arg [6] : 00000000000000000000000000000000000000000000000000000002540be400
Arg [7] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [8] : 00000000000000000000000000000000000000000000000000000500918bd800
Arg [9] : 000000000000000000000000000000000000000000000000000000012a05f200
Arg [10] : 00000000000000000000000000000000000000000000000000000000000004b0
Arg [11] : 0000000000000000000000000000000000000000000000000d3e9777fd1e2880
Arg [12] : 0000000000000000000000000ca1c1ec4ebf3cc67a9f545ff90a3795b318ca4a
Arg [13] : 000000000000000000000000cb444e90d8198415266c6a2724b7900fb12fc56e
Arg [14] : 0000000000000000000000001337bedc9d22ecbe766df105c9623922a27963ec


Block Transaction Gas Used Reward
view all blocks validated

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.