xDAI Price: $0.999328 (-0.01%)

Contract

0x056C6C5e684CeC248635eD86033378Cc444459B0
Transaction Hash
Block
From
To
Remove_liquidity442832992026-01-22 0:59:202 days ago1769043560IN
0x056C6C5e...c444459B0
0 XDAI0.000086291.5
Remove_liquidity442832942026-01-22 0:58:502 days ago1769043530IN
0x056C6C5e...c444459B0
0 XDAI0.000225751.5
Remove_liquidity442768122026-01-21 15:12:102 days ago1769008330IN
0x056C6C5e...c444459B0
0 XDAI0.00020011.5
Remove_liquidity442724132026-01-21 8:29:353 days ago1768984175IN
0x056C6C5e...c444459B0
0 XDAI0.000225771.5
Remove_liquidity442513772026-01-20 1:20:304 days ago1768872030IN
0x056C6C5e...c444459B0
0 XDAI0.000225771.5
Remove_liquidity442404102026-01-19 9:03:455 days ago1768813425IN
0x056C6C5e...c444459B0
0 XDAI0.000225771.5
Remove_liquidity442264712026-01-18 12:25:405 days ago1768739140IN
0x056C6C5e...c444459B0
0 XDAI0.000150511
Remove_liquidity441909802026-01-16 8:11:308 days ago1768551090IN
0x056C6C5e...c444459B0
0 XDAI0.000200131.5
Remove_liquidity441703112026-01-15 2:06:459 days ago1768442805IN
0x056C6C5e...c444459B0
0 XDAI0.000133411
Remove_liquidity441172852026-01-11 22:19:5012 days ago1768169990IN
0x056C6C5e...c444459B0
0 XDAI0.000225781.5
Remove_liquidity441027942026-01-11 1:44:1013 days ago1768095850IN
0x056C6C5e...c444459B0
0 XDAI0.000150511
Remove_liquidity440971582026-01-10 17:33:1013 days ago1768066390IN
0x056C6C5e...c444459B0
0 XDAI0.000225771.5
Remove_liquidity440941612026-01-10 13:16:4013 days ago1768051000IN
0x056C6C5e...c444459B0
0 XDAI0.000225781.5
Remove_liquidity440424232026-01-07 11:33:0017 days ago1767785580IN
0x056C6C5e...c444459B0
0 XDAI0.000225751.5
Remove_liquidity440417122026-01-07 10:31:0017 days ago1767781860IN
0x056C6C5e...c444459B0
0 XDAI0.000225781.5
Remove_liquidity440269812026-01-06 13:27:5017 days ago1767706070IN
0x056C6C5e...c444459B0
0 XDAI0.000200131.5
Remove_liquidity439960392026-01-04 17:11:3519 days ago1767546695IN
0x056C6C5e...c444459B0
0 XDAI0.000133411
Remove_liquidity439909952026-01-04 9:57:1520 days ago1767520635IN
0x056C6C5e...c444459B0
0 XDAI0.000200121.5
Remove_liquidity...439551112026-01-02 6:40:5022 days ago1767336050IN
0x056C6C5e...c444459B0
0 XDAI0.000441911.5
Remove_liquidity439454982026-01-01 16:53:2022 days ago1767286400IN
0x056C6C5e...c444459B0
0 XDAI0.000150511
Remove_liquidity439032182025-12-30 4:14:2025 days ago1767068060IN
0x056C6C5e...c444459B0
0 XDAI0.000225781.5
Remove_liquidity438764142025-12-28 13:23:2026 days ago1766928200IN
0x056C6C5e...c444459B0
0 XDAI0.000225771.5
Remove_liquidity438607852025-12-27 14:51:2527 days ago1766847085IN
0x056C6C5e...c444459B0
0 XDAI0.000150521
Remove_liquidity438463722025-12-26 17:46:2528 days ago1766771185IN
0x056C6C5e...c444459B0
0 XDAI0.000225771.5
Remove_liquidity438411402025-12-26 10:07:4529 days ago1766743665IN
0x056C6C5e...c444459B0
0 XDAI0.000225771.5
View all transactions

View more zero value Internal Transactions in Advanced View mode

Cross-Chain Transactions
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
Loading...
Loading
[ 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.