ETH Price: $3,394.56 (-1.12%)

Contract

0xB576491F1E6e5E62f1d8F26062Ee822B40B0E0d4
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Add_liquidity212755892024-11-27 0:44:354 hrs ago1732668275IN
0xB576491F...B40B0E0d4
0.052 ETH0.0035613711.54714839
Add_liquidity212714622024-11-26 10:55:3518 hrs ago1732618535IN
0xB576491F...B40B0E0d4
89.37628121 ETH0.002173499.98962812
Exchange_underly...212625512024-11-25 5:01:592 days ago1732510919IN
0xB576491F...B40B0E0d4
8 ETH0.001146795.86949478
Add_liquidity212615082024-11-25 1:32:472 days ago1732498367IN
0xB576491F...B40B0E0d4
0.06922224 ETH0.001928788.00284187
Exchange_underly...212609972024-11-24 23:50:232 days ago1732492223IN
0xB576491F...B40B0E0d4
0.074495 ETH0.001556317.93198352
Exchange_underly...212608392024-11-24 23:18:352 days ago1732490315IN
0xB576491F...B40B0E0d4
0.9 ETH0.001536167.29050648
Exchange_underly...212572262024-11-24 11:11:592 days ago1732446719IN
0xB576491F...B40B0E0d4
0 ETH0.002948310.67507028
Remove_liquidity...212536442024-11-23 23:12:473 days ago1732403567IN
0xB576491F...B40B0E0d4
0 ETH0.001471528.2334405
Remove_liquidity212512922024-11-23 15:19:473 days ago1732375187IN
0xB576491F...B40B0E0d4
0 ETH0.0015331618.52544809
Add_liquidity212509922024-11-23 14:19:113 days ago1732371551IN
0xB576491F...B40B0E0d4
0.055 ETH0.0047909620.17426828
Remove_liquidity...212475192024-11-23 2:42:114 days ago1732329731IN
0xB576491F...B40B0E0d4
0 ETH0.0022027312.91356191
Add_liquidity212403112024-11-22 2:33:115 days ago1732242791IN
0xB576491F...B40B0E0d4
0 ETH0.0030313111.40599615
Remove_liquidity...212389142024-11-21 21:52:115 days ago1732225931IN
0xB576491F...B40B0E0d4
0 ETH0.0033361713.3113269
Add_liquidity212388232024-11-21 21:33:595 days ago1732224839IN
0xB576491F...B40B0E0d4
0 ETH0.0041402214.67321862
Exchange_underly...212365742024-11-21 14:02:235 days ago1732197743IN
0xB576491F...B40B0E0d4
0 ETH0.0074080733.66755192
Add_liquidity212349692024-11-21 8:39:595 days ago1732178399IN
0xB576491F...B40B0E0d4
1.4 ETH0.003025999.64382074
Add_liquidity212288012024-11-20 11:58:116 days ago1732103891IN
0xB576491F...B40B0E0d4
48 ETH0.0027809210.36100309
Add_liquidity212285282024-11-20 11:03:236 days ago1732100603IN
0xB576491F...B40B0E0d4
0 ETH0.002480118.55650727
Add_liquidity212237112024-11-19 18:56:117 days ago1732042571IN
0xB576491F...B40B0E0d4
0.1 ETH0.0070746824.96535774
Add_liquidity212232312024-11-19 17:19:597 days ago1732036799IN
0xB576491F...B40B0E0d4
0 ETH0.005110423.58439366
Exchange_underly...212231932024-11-19 17:12:237 days ago1732036343IN
0xB576491F...B40B0E0d4
0 ETH0.0052044421.69080474
Exchange_underly...212230112024-11-19 16:35:597 days ago1732034159IN
0xB576491F...B40B0E0d4
0 ETH0.0057507223.3512045
Exchange_underly...212228822024-11-19 16:09:597 days ago1732032599IN
0xB576491F...B40B0E0d4
0 ETH0.004539620.18662902
Remove_liquidity...212154532024-11-18 15:19:118 days ago1731943151IN
0xB576491F...B40B0E0d4
0 ETH0.0026958215.99432324
Remove_liquidity...212104382024-11-17 22:32:479 days ago1731882767IN
0xB576491F...B40B0E0d4
0 ETH0.0020654810.89312851
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
212768962024-11-27 5:07:594 mins ago1732684079
0xB576491F...B40B0E0d4
0.53752115 ETH
212768912024-11-27 5:06:595 mins ago1732684019
0xB576491F...B40B0E0d4
0.11101506 ETH
212767512024-11-27 4:38:4733 mins ago1732682327
0xB576491F...B40B0E0d4
2.01034841 ETH
212767112024-11-27 4:30:3541 mins ago1732681835
0xB576491F...B40B0E0d4
2.00808445 ETH
212767012024-11-27 4:28:2344 mins ago1732681703
0xB576491F...B40B0E0d4
0.00117253 ETH
212766142024-11-27 4:10:591 hr ago1732680659
0xB576491F...B40B0E0d4
0.00441956 ETH
212763662024-11-27 3:20:591 hr ago1732677659
0xB576491F...B40B0E0d4
2.00811379 ETH
212761792024-11-27 2:43:352 hrs ago1732675415
0xB576491F...B40B0E0d4
2.00819288 ETH
212760792024-11-27 2:23:352 hrs ago1732674215
0xB576491F...B40B0E0d4
2.01291248 ETH
212760682024-11-27 2:21:232 hrs ago1732674083
0xB576491F...B40B0E0d4
2.00804904 ETH
212760432024-11-27 2:16:232 hrs ago1732673783
0xB576491F...B40B0E0d4
2.00843546 ETH
212760332024-11-27 2:14:232 hrs ago1732673663
0xB576491F...B40B0E0d4
2.01139815 ETH
212757152024-11-27 1:09:474 hrs ago1732669787
0xB576491F...B40B0E0d4
0.00000186 ETH
212757152024-11-27 1:09:474 hrs ago1732669787
0xB576491F...B40B0E0d4
0.02013991 ETH
212755962024-11-27 0:45:594 hrs ago1732668359
0xB576491F...B40B0E0d4
3.86263035 ETH
212754882024-11-27 0:23:594 hrs ago1732667039
0xB576491F...B40B0E0d4
0.96953381 ETH
212753432024-11-26 23:54:475 hrs ago1732665287
0xB576491F...B40B0E0d4
0.00923772 ETH
212753432024-11-26 23:54:475 hrs ago1732665287
0xB576491F...B40B0E0d4
0.10647827 ETH
212752692024-11-26 23:39:595 hrs ago1732664399
0xB576491F...B40B0E0d4
0.00449338 ETH
212752692024-11-26 23:39:595 hrs ago1732664399
0xB576491F...B40B0E0d4
0.00174013 ETH
212751932024-11-26 23:24:475 hrs ago1732663487
0xB576491F...B40B0E0d4
0.00116745 ETH
212751762024-11-26 23:21:235 hrs ago1732663283
0xB576491F...B40B0E0d4
0.13190147 ETH
212751682024-11-26 23:19:475 hrs ago1732663187
0xB576491F...B40B0E0d4
0.00705834 ETH
212751352024-11-26 23:13:115 hrs ago1732662791
0xB576491F...B40B0E0d4
2.0080652 ETH
212751152024-11-26 23:09:116 hrs ago1732662551
0xB576491F...B40B0E0d4
3.29025664 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Vyper_contract

Compiler Version
vyper:0.3.1

Optimization Enabled:
N/A

Other Settings:
MIT license

Contract Source Code (Vyper language format)

# @version 0.3.1
# (c) Curve.Fi, 2021
# Pool for two crypto assets

# Expected coins:
# eth/whatever

interface CurveToken:
    def totalSupply() -> uint256: view
    def mint(_to: address, _value: uint256) -> bool: nonpayable
    def mint_relative(_to: address, frac: uint256) -> uint256: nonpayable
    def burnFrom(_to: address, _value: uint256) -> bool: nonpayable

interface ERC20:
    def transfer(_to: address, _value: uint256) -> bool: nonpayable
    def transferFrom(_from: address, _to: address, _value: uint256) -> bool: nonpayable
    def decimals() -> uint256: view
    def balanceOf(_user: address) -> uint256: view

interface WETH:
    def deposit(): payable
    def withdraw(_amount: uint256): nonpayable


# Events
event TokenExchange:
    buyer: indexed(address)
    sold_id: uint256
    tokens_sold: uint256
    bought_id: uint256
    tokens_bought: uint256

event AddLiquidity:
    provider: indexed(address)
    token_amounts: uint256[N_COINS]
    fee: uint256
    token_supply: uint256

event RemoveLiquidity:
    provider: indexed(address)
    token_amounts: uint256[N_COINS]
    token_supply: uint256

event RemoveLiquidityOne:
    provider: indexed(address)
    token_amount: uint256
    coin_index: uint256
    coin_amount: uint256

event CommitNewAdmin:
    deadline: indexed(uint256)
    admin: indexed(address)

event NewAdmin:
    admin: indexed(address)

event CommitNewParameters:
    deadline: indexed(uint256)
    admin_fee: uint256
    mid_fee: uint256
    out_fee: uint256
    fee_gamma: uint256
    allowed_extra_profit: uint256
    adjustment_step: uint256
    ma_half_time: uint256

event NewParameters:
    admin_fee: uint256
    mid_fee: uint256
    out_fee: uint256
    fee_gamma: uint256
    allowed_extra_profit: uint256
    adjustment_step: uint256
    ma_half_time: uint256

event RampAgamma:
    initial_A: uint256
    future_A: uint256
    initial_gamma: uint256
    future_gamma: uint256
    initial_time: uint256
    future_time: uint256

event StopRampA:
    current_A: uint256
    current_gamma: uint256
    time: uint256

event ClaimAdminFee:
    admin: indexed(address)
    tokens: uint256


N_COINS: constant(int128) = 2
PRECISION: constant(uint256) = 10 ** 18  # The precision to convert to
A_MULTIPLIER: constant(uint256) = 10000

token: immutable(address)
coins: immutable(address[N_COINS])

price_scale: public(uint256)   # Internal price scale
price_oracle: public(uint256)  # Price target given by MA

last_prices: public(uint256)
last_prices_timestamp: public(uint256)

initial_A_gamma: public(uint256)
future_A_gamma: public(uint256)
initial_A_gamma_time: public(uint256)
future_A_gamma_time: public(uint256)

allowed_extra_profit: public(uint256)  # 2 * 10**12 - recommended value
future_allowed_extra_profit: public(uint256)

fee_gamma: public(uint256)
future_fee_gamma: public(uint256)

adjustment_step: public(uint256)
future_adjustment_step: public(uint256)

ma_half_time: public(uint256)
future_ma_half_time: public(uint256)

mid_fee: public(uint256)
out_fee: public(uint256)
admin_fee: public(uint256)
future_mid_fee: public(uint256)
future_out_fee: public(uint256)
future_admin_fee: public(uint256)

balances: public(uint256[N_COINS])
D: public(uint256)

owner: public(address)
future_owner: public(address)

xcp_profit: public(uint256)
xcp_profit_a: public(uint256)  # Full profit at last claim of admin fees
virtual_price: public(uint256)  # Cached (fast to read) virtual price also used internally
not_adjusted: bool

is_killed: public(bool)
kill_deadline: public(uint256)
transfer_ownership_deadline: public(uint256)
admin_actions_deadline: public(uint256)

admin_fee_receiver: public(address)

KILL_DEADLINE_DT: constant(uint256) = 2 * 30 * 86400
ADMIN_ACTIONS_DELAY: constant(uint256) = 3 * 86400
MIN_RAMP_TIME: constant(uint256) = 86400

MAX_ADMIN_FEE: constant(uint256) = 10 * 10 ** 9
MIN_FEE: constant(uint256) = 5 * 10 ** 5  # 0.5 bps
MAX_FEE: constant(uint256) = 10 * 10 ** 9
MAX_A_CHANGE: constant(uint256) = 10
NOISE_FEE: constant(uint256) = 10**5  # 0.1 bps

MIN_GAMMA: constant(uint256) = 10**10
MAX_GAMMA: constant(uint256) = 2 * 10**16

MIN_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER / 10
MAX_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER * 100000

# This must be changed for different N_COINS
# For example:
# N_COINS = 3 -> 1  (10**18 -> 10**18)
# N_COINS = 4 -> 10**8  (10**18 -> 10**10)
# PRICE_PRECISION_MUL: constant(uint256) = 1
PRECISIONS: immutable(uint256[N_COINS])

EXP_PRECISION: constant(uint256) = 10**10

ETH_INDEX: constant(uint256) = 0  # Can put it to something big to turn the logic off


@external
def __init__(
    owner: address,
    admin_fee_receiver: address,
    A: uint256,
    gamma: uint256,
    mid_fee: uint256,
    out_fee: uint256,
    allowed_extra_profit: uint256,
    fee_gamma: uint256,
    adjustment_step: uint256,
    admin_fee: uint256,
    ma_half_time: uint256,
    initial_price: uint256,
    _token: address,
    _coins: address[N_COINS]
):
    self.owner = owner

    # Pack A and gamma:
    # shifted A + gamma
    A_gamma: uint256 = shift(A, 128)
    A_gamma = bitwise_or(A_gamma, gamma)
    self.initial_A_gamma = A_gamma
    self.future_A_gamma = A_gamma

    self.mid_fee = mid_fee
    self.out_fee = out_fee
    self.allowed_extra_profit = allowed_extra_profit
    self.fee_gamma = fee_gamma
    self.adjustment_step = adjustment_step
    self.admin_fee = admin_fee

    self.price_scale = initial_price
    self.price_oracle = initial_price
    self.last_prices = initial_price
    self.last_prices_timestamp = block.timestamp
    self.ma_half_time = ma_half_time

    self.xcp_profit_a = 10**18

    self.kill_deadline = block.timestamp + KILL_DEADLINE_DT

    self.admin_fee_receiver = admin_fee_receiver

    token = _token
    coins = _coins
    PRECISIONS = [10 ** (18 - ERC20(_coins[0]).decimals()),
                  10 ** (18 - ERC20(_coins[1]).decimals())]


@payable
@external
def __default__():
    pass


### Math functions
@internal
@pure
def geometric_mean(unsorted_x: uint256[N_COINS], sort: bool) -> uint256:
    """
    (x[0] * x[1] * ...) ** (1/N)
    """
    x: uint256[N_COINS] = unsorted_x
    if sort and x[0] < x[1]:
        x = [unsorted_x[1], unsorted_x[0]]
    D: uint256 = x[0]
    diff: uint256 = 0
    for i in range(255):
        D_prev: uint256 = D
        # tmp: uint256 = 10**18
        # for _x in x:
        #     tmp = tmp * _x / D
        # D = D * ((N_COINS - 1) * 10**18 + tmp) / (N_COINS * 10**18)
        # line below makes it for 2 coins
        D = (D + x[0] * x[1] / D) / N_COINS
        if D > D_prev:
            diff = D - D_prev
        else:
            diff = D_prev - D
        if diff <= 1 or diff * 10**18 < D:
            return D
    raise "Did not converge"


@internal
@view
def newton_D(ANN: uint256, gamma: uint256, x_unsorted: uint256[N_COINS]) -> uint256:
    """
    Finding the invariant using Newton method.
    ANN is higher by the factor A_MULTIPLIER
    ANN is already A * N**N

    Currently uses 60k gas
    """
    # Safety checks
    assert ANN > MIN_A - 1 and ANN < MAX_A + 1  # dev: unsafe values A
    assert gamma > MIN_GAMMA - 1 and gamma < MAX_GAMMA + 1  # dev: unsafe values gamma

    # Initial value of invariant D is that for constant-product invariant
    x: uint256[N_COINS] = x_unsorted
    if x[0] < x[1]:
        x = [x_unsorted[1], x_unsorted[0]]

    assert x[0] > 10**9 - 1 and x[0] < 10**15 * 10**18 + 1  # dev: unsafe values x[0]
    assert x[1] * 10**18 / x[0] > 10**14-1  # dev: unsafe values x[i] (input)

    D: uint256 = N_COINS * self.geometric_mean(x, False)
    S: uint256 = x[0] + x[1]

    for i in range(255):
        D_prev: uint256 = D

        # K0: uint256 = 10**18
        # for _x in x:
        #     K0 = K0 * _x * N_COINS / D
        # collapsed for 2 coins
        K0: uint256 = (10**18 * N_COINS**2) * x[0] / D * x[1] / D

        _g1k0: uint256 = gamma + 10**18
        if _g1k0 > K0:
            _g1k0 = _g1k0 - K0 + 1
        else:
            _g1k0 = K0 - _g1k0 + 1

        # D / (A * N**N) * _g1k0**2 / gamma**2
        mul1: uint256 = 10**18 * D / gamma * _g1k0 / gamma * _g1k0 * A_MULTIPLIER / ANN

        # 2*N*K0 / _g1k0
        mul2: uint256 = (2 * 10**18) * N_COINS * K0 / _g1k0

        neg_fprime: uint256 = (S + S * mul2 / 10**18) + mul1 * N_COINS / K0 - mul2 * D / 10**18

        # D -= f / fprime
        D_plus: uint256 = D * (neg_fprime + S) / neg_fprime
        D_minus: uint256 = D*D / neg_fprime
        if 10**18 > K0:
            D_minus += D * (mul1 / neg_fprime) / 10**18 * (10**18 - K0) / K0
        else:
            D_minus -= D * (mul1 / neg_fprime) / 10**18 * (K0 - 10**18) / K0

        if D_plus > D_minus:
            D = D_plus - D_minus
        else:
            D = (D_minus - D_plus) / 2

        diff: uint256 = 0
        if D > D_prev:
            diff = D - D_prev
        else:
            diff = D_prev - D
        if diff * 10**14 < max(10**16, D):  # Could reduce precision for gas efficiency here
            # Test that we are safe with the next newton_y
            for _x in x:
                frac: uint256 = _x * 10**18 / D
                assert (frac > 10**16 - 1) and (frac < 10**20 + 1)  # dev: unsafe values x[i]
            return D

    raise "Did not converge"


@internal
@pure
def newton_y(ANN: uint256, gamma: uint256, x: uint256[N_COINS], D: uint256, i: uint256) -> uint256:
    """
    Calculating x[i] given other balances x[0..N_COINS-1] and invariant D
    ANN = A * N**N
    """
    # Safety checks
    assert ANN > MIN_A - 1 and ANN < MAX_A + 1  # dev: unsafe values A
    assert gamma > MIN_GAMMA - 1 and gamma < MAX_GAMMA + 1  # dev: unsafe values gamma
    assert D > 10**17 - 1 and D < 10**15 * 10**18 + 1 # dev: unsafe values D

    x_j: uint256 = x[1 - i]
    y: uint256 = D**2 / (x_j * N_COINS**2)
    K0_i: uint256 = (10**18 * N_COINS) * x_j / D
    # S_i = x_j

    # frac = x_j * 1e18 / D => frac = K0_i / N_COINS
    assert (K0_i > 10**16*N_COINS - 1) and (K0_i < 10**20*N_COINS + 1)  # dev: unsafe values x[i]

    # x_sorted: uint256[N_COINS] = x
    # x_sorted[i] = 0
    # x_sorted = self.sort(x_sorted)  # From high to low
    # x[not i] instead of x_sorted since x_soted has only 1 element

    convergence_limit: uint256 = max(max(x_j / 10**14, D / 10**14), 100)

    for j in range(255):
        y_prev: uint256 = y

        K0: uint256 = K0_i * y * N_COINS / D
        S: uint256 = x_j + y

        _g1k0: uint256 = gamma + 10**18
        if _g1k0 > K0:
            _g1k0 = _g1k0 - K0 + 1
        else:
            _g1k0 = K0 - _g1k0 + 1

        # D / (A * N**N) * _g1k0**2 / gamma**2
        mul1: uint256 = 10**18 * D / gamma * _g1k0 / gamma * _g1k0 * A_MULTIPLIER / ANN

        # 2*K0 / _g1k0
        mul2: uint256 = 10**18 + (2 * 10**18) * K0 / _g1k0

        yfprime: uint256 = 10**18 * y + S * mul2 + mul1
        _dyfprime: uint256 = D * mul2
        if yfprime < _dyfprime:
            y = y_prev / 2
            continue
        else:
            yfprime -= _dyfprime
        fprime: uint256 = yfprime / y

        # y -= f / f_prime;  y = (y * fprime - f) / fprime
        # y = (yfprime + 10**18 * D - 10**18 * S) // fprime + mul1 // fprime * (10**18 - K0) // K0
        y_minus: uint256 = mul1 / fprime
        y_plus: uint256 = (yfprime + 10**18 * D) / fprime + y_minus * 10**18 / K0
        y_minus += 10**18 * S / fprime

        if y_plus < y_minus:
            y = y_prev / 2
        else:
            y = y_plus - y_minus

        diff: uint256 = 0
        if y > y_prev:
            diff = y - y_prev
        else:
            diff = y_prev - y
        if diff < max(convergence_limit, y / 10**14):
            frac: uint256 = y * 10**18 / D
            assert (frac > 10**16 - 1) and (frac < 10**20 + 1)  # dev: unsafe value for y
            return y

    raise "Did not converge"


@internal
@pure
def halfpow(power: uint256) -> uint256:
    """
    1e18 * 0.5 ** (power/1e18)

    Inspired by: https://github.com/balancer-labs/balancer-core/blob/master/contracts/BNum.sol#L128
    """
    intpow: uint256 = power / 10**18
    otherpow: uint256 = power - intpow * 10**18
    if intpow > 59:
        return 0
    result: uint256 = 10**18 / (2**intpow)
    if otherpow == 0:
        return result

    term: uint256 = 10**18
    x: uint256 = 5 * 10**17
    S: uint256 = 10**18
    neg: bool = False

    for i in range(1, 256):
        K: uint256 = i * 10**18
        c: uint256 = K - 10**18
        if otherpow > c:
            c = otherpow - c
            neg = not neg
        else:
            c -= otherpow
        term = term * (c * x / 10**18) / K
        if neg:
            S -= term
        else:
            S += term
        if term < EXP_PRECISION:
            return result * S / 10**18

    raise "Did not converge"
### end of Math functions


@external
@view
def token() -> address:
    return token


@external
@view
def coins(i: uint256) -> address:
    _coins: address[N_COINS] = coins
    return _coins[i]


@internal
@view
def xp() -> uint256[N_COINS]:
    return [self.balances[0] * PRECISIONS[0],
            self.balances[1] * PRECISIONS[1] * self.price_scale / PRECISION]


@view
@internal
def _A_gamma() -> uint256[2]:
    t1: uint256 = self.future_A_gamma_time

    A_gamma_1: uint256 = self.future_A_gamma
    gamma1: uint256 = bitwise_and(A_gamma_1, 2**128-1)
    A1: uint256 = shift(A_gamma_1, -128)

    if block.timestamp < t1:
        # handle ramping up and down of A
        A_gamma_0: uint256 = self.initial_A_gamma
        t0: uint256 = self.initial_A_gamma_time

        # Less readable but more compact way of writing and converting to uint256
        # gamma0: uint256 = bitwise_and(A_gamma_0, 2**128-1)
        # A0: uint256 = shift(A_gamma_0, -128)
        # A1 = A0 + (A1 - A0) * (block.timestamp - t0) / (t1 - t0)
        # gamma1 = gamma0 + (gamma1 - gamma0) * (block.timestamp - t0) / (t1 - t0)

        t1 -= t0
        t0 = block.timestamp - t0
        t2: uint256 = t1 - t0

        A1 = (shift(A_gamma_0, -128) * t2 + A1 * t0) / t1
        gamma1 = (bitwise_and(A_gamma_0, 2**128-1) * t2 + gamma1 * t0) / t1

    return [A1, gamma1]


@view
@external
def A() -> uint256:
    return self._A_gamma()[0]


@view
@external
def gamma() -> uint256:
    return self._A_gamma()[1]


@internal
@view
def _fee(xp: uint256[N_COINS]) -> uint256:
    """
    f = fee_gamma / (fee_gamma + (1 - K))
    where
    K = prod(x) / (sum(x) / N)**N
    (all normalized to 1e18)
    """
    fee_gamma: uint256 = self.fee_gamma
    f: uint256 = xp[0] + xp[1]  # sum
    f = fee_gamma * 10**18 / (
        fee_gamma + 10**18 - (10**18 * N_COINS**N_COINS) * xp[0] / f * xp[1] / f
    )
    return (self.mid_fee * f + self.out_fee * (10**18 - f)) / 10**18


@external
@view
def fee() -> uint256:
    return self._fee(self.xp())


@internal
@view
def get_xcp(D: uint256) -> uint256:
    x: uint256[N_COINS] = [D / N_COINS, D * PRECISION / (self.price_scale * N_COINS)]
    return self.geometric_mean(x, True)


@external
@view
def get_virtual_price() -> uint256:
    return 10**18 * self.get_xcp(self.D) / CurveToken(token).totalSupply()


@internal
def _claim_admin_fees():
    A_gamma: uint256[2] = self._A_gamma()

    xcp_profit: uint256 = self.xcp_profit
    xcp_profit_a: uint256 = self.xcp_profit_a

    # Gulp here
    _coins: address[N_COINS] = coins
    for i in range(N_COINS):
        if i == ETH_INDEX:
            self.balances[i] = self.balance
        else:
            self.balances[i] = ERC20(_coins[i]).balanceOf(self)

    vprice: uint256 = self.virtual_price

    if xcp_profit > xcp_profit_a:
        fees: uint256 = (xcp_profit - xcp_profit_a) * self.admin_fee / (2 * 10**10)
        if fees > 0:
            receiver: address = self.admin_fee_receiver
            if receiver != ZERO_ADDRESS:
                frac: uint256 = vprice * 10**18 / (vprice - fees) - 10**18
                claimed: uint256 = CurveToken(token).mint_relative(receiver, frac)
                xcp_profit -= fees*2
                self.xcp_profit = xcp_profit
                log ClaimAdminFee(receiver, claimed)

    total_supply: uint256 = CurveToken(token).totalSupply()

    # Recalculate D b/c we gulped
    D: uint256 = self.newton_D(A_gamma[0], A_gamma[1], self.xp())
    self.D = D

    self.virtual_price = 10**18 * self.get_xcp(D) / total_supply

    if xcp_profit > xcp_profit_a:
        self.xcp_profit_a = xcp_profit


@internal
def tweak_price(A_gamma: uint256[2],_xp: uint256[N_COINS], p_i: uint256, new_D: uint256):
    price_oracle: uint256 = self.price_oracle
    last_prices: uint256 = self.last_prices
    price_scale: uint256 = self.price_scale
    last_prices_timestamp: uint256 = self.last_prices_timestamp
    p_new: uint256 = 0

    if last_prices_timestamp < block.timestamp:
        # MA update required
        ma_half_time: uint256 = self.ma_half_time
        alpha: uint256 = self.halfpow((block.timestamp - last_prices_timestamp) * 10**18 / ma_half_time)
        price_oracle = (last_prices * (10**18 - alpha) + price_oracle * alpha) / 10**18
        self.price_oracle = price_oracle
        self.last_prices_timestamp = block.timestamp

    D_unadjusted: uint256 = new_D  # Withdrawal methods know new D already
    if new_D == 0:
        # We will need this a few times (35k gas)
        D_unadjusted = self.newton_D(A_gamma[0], A_gamma[1], _xp)

    if p_i > 0:
        last_prices = p_i

    else:
        # calculate real prices
        __xp: uint256[N_COINS] = _xp
        dx_price: uint256 = __xp[0] / 10**6
        __xp[0] += dx_price
        last_prices = price_scale * dx_price / (_xp[1] - self.newton_y(A_gamma[0], A_gamma[1], __xp, D_unadjusted, 1))

    self.last_prices = last_prices

    total_supply: uint256 = CurveToken(token).totalSupply()
    old_xcp_profit: uint256 = self.xcp_profit
    old_virtual_price: uint256 = self.virtual_price

    # Update profit numbers without price adjustment first
    xp: uint256[N_COINS] = [D_unadjusted / N_COINS, D_unadjusted * PRECISION / (N_COINS * price_scale)]
    xcp_profit: uint256 = 10**18
    virtual_price: uint256 = 10**18

    if old_virtual_price > 0:
        xcp: uint256 = self.geometric_mean(xp, True)
        virtual_price = 10**18 * xcp / total_supply
        xcp_profit = old_xcp_profit * virtual_price / old_virtual_price

        t: uint256 = self.future_A_gamma_time
        if virtual_price < old_virtual_price and t == 0:
            raise "Loss"
        if t == 1:
            self.future_A_gamma_time = 0

    self.xcp_profit = xcp_profit

    norm: uint256 = price_oracle * 10**18 / price_scale
    if norm > 10**18:
        norm -= 10**18
    else:
        norm = 10**18 - norm
    adjustment_step: uint256 = max(self.adjustment_step, norm / 10)

    needs_adjustment: bool = self.not_adjusted
    # if not needs_adjustment and (virtual_price-10**18 > (xcp_profit-10**18)/2 + self.allowed_extra_profit):
    # (re-arrange for gas efficiency)
    if not needs_adjustment and (virtual_price * 2 - 10**18 > xcp_profit + 2*self.allowed_extra_profit) and (norm > adjustment_step) and (old_virtual_price > 0):
        needs_adjustment = True
        self.not_adjusted = True

    if needs_adjustment:
        if norm > adjustment_step and old_virtual_price > 0:
            p_new = (price_scale * (norm - adjustment_step) + adjustment_step * price_oracle) / norm

            # Calculate balances*prices
            xp = [_xp[0], _xp[1] * p_new / price_scale]

            # Calculate "extended constant product" invariant xCP and virtual price
            D: uint256 = self.newton_D(A_gamma[0], A_gamma[1], xp)
            xp = [D / N_COINS, D * PRECISION / (N_COINS * p_new)]
            # We reuse old_virtual_price here but it's not old anymore
            old_virtual_price = 10**18 * self.geometric_mean(xp, True) / total_supply

            # Proceed if we've got enough profit
            # if (old_virtual_price > 10**18) and (2 * (old_virtual_price - 10**18) > xcp_profit - 10**18):
            if (old_virtual_price > 10**18) and (2 * old_virtual_price - 10**18 > xcp_profit):
                self.price_scale = p_new
                self.D = D
                self.virtual_price = old_virtual_price

                return

            else:
                self.not_adjusted = False

                # Can instead do another flag variable if we want to save bytespace
                self.D = D_unadjusted
                self.virtual_price = virtual_price
                self._claim_admin_fees()

                return

    # If we are here, the price_scale adjustment did not happen
    # Still need to update the profit counter and D
    self.D = D_unadjusted
    self.virtual_price = virtual_price

    # norm appeared < adjustment_step after
    if needs_adjustment:
        self.not_adjusted = False
        self._claim_admin_fees()


@internal
def _exchange(sender: address, mvalue: uint256, i: uint256, j: uint256, dx: uint256, min_dy: uint256, use_eth: bool) -> uint256:
    assert not self.is_killed  # dev: the pool is killed
    assert i != j  # dev: coin index out of range
    assert i < N_COINS  # dev: coin index out of range
    assert j < N_COINS  # dev: coin index out of range
    assert dx > 0  # dev: do not exchange 0 coins

    A_gamma: uint256[2] = self._A_gamma()
    xp: uint256[N_COINS] = self.balances
    p: uint256 = 0
    dy: uint256 = 0

    _coins: address[N_COINS] = coins
    if use_eth and i == ETH_INDEX:
        assert mvalue == dx  # dev: incorrect eth amount
    else:
        assert mvalue == 0  # dev: nonzero eth amount
        assert ERC20(_coins[i]).transferFrom(sender, self, dx)
        if i == ETH_INDEX:
            WETH(_coins[i]).withdraw(dx)

    y: uint256 = xp[j]
    x0: uint256 = xp[i]
    xp[i] = x0 + dx
    self.balances[i] = xp[i]

    price_scale: uint256 = self.price_scale

    xp = [xp[0] * PRECISIONS[0], xp[1] * price_scale * PRECISIONS[1] / PRECISION]

    prec_i: uint256 = PRECISIONS[0]
    prec_j: uint256 = PRECISIONS[1]
    if i == 1:
        prec_i = PRECISIONS[1]
        prec_j = PRECISIONS[0]

    # In case ramp is happening
    t: uint256 = self.future_A_gamma_time
    if t > 0:
        x0 *= prec_i
        if i > 0:
            x0 = x0 * price_scale / PRECISION
        x1: uint256 = xp[i]  # Back up old value in xp
        xp[i] = x0
        self.D = self.newton_D(A_gamma[0], A_gamma[1], xp)
        xp[i] = x1  # And restore
        if block.timestamp >= t:
            self.future_A_gamma_time = 1

    dy = xp[j] - self.newton_y(A_gamma[0], A_gamma[1], xp, self.D, j)
    # Not defining new "y" here to have less variables / make subsequent calls cheaper
    xp[j] -= dy
    dy -= 1

    if j > 0:
        dy = dy * PRECISION / price_scale
    dy /= prec_j

    dy -= self._fee(xp) * dy / 10**10
    assert dy >= min_dy, "Slippage"
    y -= dy

    self.balances[j] = y
    if use_eth and j == ETH_INDEX:
        raw_call(sender, b"", value=dy)
    else:
        if j == ETH_INDEX:
            WETH(_coins[j]).deposit(value=dy)
        assert ERC20(_coins[j]).transfer(sender, dy)

    y *= prec_j
    if j > 0:
        y = y * price_scale / PRECISION
    xp[j] = y

    # Calculate price
    if dx > 10**5 and dy > 10**5:
        _dx: uint256 = dx * prec_i
        _dy: uint256 = dy * prec_j
        if i == 0:
            p = _dx * 10**18 / _dy
        else:  # j == 0
            p = _dy * 10**18 / _dx

    self.tweak_price(A_gamma, xp, p, 0)

    log TokenExchange(sender, i, dx, j, dy)

    return dy


@payable
@external
@nonreentrant('lock')
def exchange(i: uint256, j: uint256, dx: uint256, min_dy: uint256, use_eth: bool = False) -> uint256:
    """
    Exchange using WETH by default
    """
    return self._exchange(msg.sender, msg.value, i, j, dx, min_dy, use_eth)


@payable
@external
@nonreentrant('lock')
def exchange_underlying(i: uint256, j: uint256, dx: uint256, min_dy: uint256) -> uint256:
    """
    Exchange using ETH
    """
    return self._exchange(msg.sender, msg.value, i, j, dx, min_dy, True)


@external
@view
def get_dy(i: uint256, j: uint256, dx: uint256) -> uint256:
    assert i != j  # dev: same input and output coin
    assert i < N_COINS  # dev: coin index out of range
    assert j < N_COINS  # dev: coin index out of range

    price_scale: uint256 = self.price_scale * PRECISIONS[1]
    xp: uint256[N_COINS] = self.balances

    A_gamma: uint256[2] = self._A_gamma()
    D: uint256 = self.D
    if self.future_A_gamma_time > 0:
        D = self.newton_D(A_gamma[0], A_gamma[1], self.xp())

    xp[i] += dx
    xp = [xp[0] * PRECISIONS[0], xp[1] * price_scale / PRECISION]

    y: uint256 = self.newton_y(A_gamma[0], A_gamma[1], xp, D, j)
    dy: uint256 = xp[j] - y - 1
    xp[j] = y
    if j > 0:
        dy = dy * PRECISION / price_scale
    else:
        dy /= PRECISIONS[0]
    dy -= self._fee(xp) * dy / 10**10

    return dy


@view
@internal
def _calc_token_fee(amounts: uint256[N_COINS], xp: uint256[N_COINS]) -> uint256:
    # fee = sum(amounts_i - avg(amounts)) * fee' / sum(amounts)
    fee: uint256 = self._fee(xp) * N_COINS / (4 * (N_COINS-1))
    S: uint256 = 0
    for _x in amounts:
        S += _x
    avg: uint256 = S / N_COINS
    Sdiff: uint256 = 0
    for _x in amounts:
        if _x > avg:
            Sdiff += _x - avg
        else:
            Sdiff += avg - _x
    return fee * Sdiff / S + NOISE_FEE


@payable
@external
@nonreentrant('lock')
def add_liquidity(amounts: uint256[N_COINS], min_mint_amount: uint256, use_eth: bool = False) -> uint256:
    assert not self.is_killed  # dev: the pool is killed
    assert amounts[0] > 0 or amounts[1] > 0  # dev: no coins to add

    A_gamma: uint256[2] = self._A_gamma()

    _coins: address[N_COINS] = coins

    xp: uint256[N_COINS] = self.balances
    amountsp: uint256[N_COINS] = empty(uint256[N_COINS])
    xx: uint256[N_COINS] = empty(uint256[N_COINS])
    d_token: uint256 = 0
    d_token_fee: uint256 = 0
    old_D: uint256 = 0

    xp_old: uint256[N_COINS] = xp

    for i in range(N_COINS):
        bal: uint256 = xp[i] + amounts[i]
        xp[i] = bal
        self.balances[i] = bal
    xx = xp

    price_scale: uint256 = self.price_scale * PRECISIONS[1]
    xp = [xp[0] * PRECISIONS[0], xp[1] * price_scale / PRECISION]
    xp_old = [xp_old[0] * PRECISIONS[0], xp_old[1] * price_scale / PRECISION]

    if not use_eth:
        assert msg.value == 0  # dev: nonzero eth amount

    for i in range(N_COINS):
        if use_eth and i == ETH_INDEX:
            assert msg.value == amounts[i]  # dev: incorrect eth amount
        if amounts[i] > 0:
            if (not use_eth) or (i != ETH_INDEX):
                assert ERC20(_coins[i]).transferFrom(msg.sender, self, amounts[i])
                if i == ETH_INDEX:
                    WETH(_coins[i]).withdraw(amounts[i])
            amountsp[i] = xp[i] - xp_old[i]

    t: uint256 = self.future_A_gamma_time
    if t > 0:
        old_D = self.newton_D(A_gamma[0], A_gamma[1], xp_old)
        if block.timestamp >= t:
            self.future_A_gamma_time = 1
    else:
        old_D = self.D

    D: uint256 = self.newton_D(A_gamma[0], A_gamma[1], xp)

    token_supply: uint256 = CurveToken(token).totalSupply()
    if old_D > 0:
        d_token = token_supply * D / old_D - token_supply
    else:
        d_token = self.get_xcp(D)  # making initial virtual price equal to 1
    assert d_token > 0  # dev: nothing minted

    if old_D > 0:
        d_token_fee = self._calc_token_fee(amountsp, xp) * d_token / 10**10 + 1
        d_token -= d_token_fee
        token_supply += d_token
        CurveToken(token).mint(msg.sender, d_token)

        # Calculate price
        # p_i * (dx_i - dtoken / token_supply * xx_i) = sum{k!=i}(p_k * (dtoken / token_supply * xx_k - dx_k))
        # Simplified for 2 coins
        p: uint256 = 0
        if d_token > 10**5:
            if amounts[0] == 0 or amounts[1] == 0:
                S: uint256 = 0
                precision: uint256 = 0
                ix: uint256 = 0
                if amounts[0] == 0:
                    S = xx[0] * PRECISIONS[0]
                    precision = PRECISIONS[1]
                    ix = 1
                else:
                    S = xx[1] * PRECISIONS[1]
                    precision = PRECISIONS[0]
                S = S * d_token / token_supply
                p = S * PRECISION / (amounts[ix] * precision - d_token * xx[ix] * precision / token_supply)
                if ix == 0:
                    p = (10**18)**2 / p

        self.tweak_price(A_gamma, xp, p, D)

    else:
        self.D = D
        self.virtual_price = 10**18
        self.xcp_profit = 10**18
        CurveToken(token).mint(msg.sender, d_token)

    assert d_token >= min_mint_amount, "Slippage"

    log AddLiquidity(msg.sender, amounts, d_token_fee, token_supply)

    return d_token


@external
@nonreentrant('lock')
def remove_liquidity(_amount: uint256, min_amounts: uint256[N_COINS], use_eth: bool = False):
    """
    This withdrawal method is very safe, does no complex math
    """
    _coins: address[N_COINS] = coins
    total_supply: uint256 = CurveToken(token).totalSupply()
    CurveToken(token).burnFrom(msg.sender, _amount)
    balances: uint256[N_COINS] = self.balances
    amount: uint256 = _amount - 1  # Make rounding errors favoring other LPs a tiny bit

    for i in range(N_COINS):
        d_balance: uint256 = balances[i] * amount / total_supply
        assert d_balance >= min_amounts[i]
        self.balances[i] = balances[i] - d_balance
        balances[i] = d_balance  # now it's the amounts going out
        if use_eth and i == ETH_INDEX:
            raw_call(msg.sender, b"", value=d_balance)
        else:
            if i == ETH_INDEX:
                WETH(_coins[i]).deposit(value=d_balance)
            assert ERC20(_coins[i]).transfer(msg.sender, d_balance)

    D: uint256 = self.D
    self.D = D - D * amount / total_supply

    log RemoveLiquidity(msg.sender, balances, total_supply - _amount)


@view
@external
def calc_token_amount(amounts: uint256[N_COINS]) -> uint256:
    token_supply: uint256 = CurveToken(token).totalSupply()
    price_scale: uint256 = self.price_scale * PRECISIONS[1]
    A_gamma: uint256[2] = self._A_gamma()
    xp: uint256[N_COINS] = self.xp()
    amountsp: uint256[N_COINS] = [
        amounts[0] * PRECISIONS[0],
        amounts[1] * price_scale / PRECISION]
    D0: uint256 = self.D
    if self.future_A_gamma_time > 0:
        D0 = self.newton_D(A_gamma[0], A_gamma[1], xp)
    xp[0] += amountsp[0]
    xp[1] += amountsp[1]
    D: uint256 = self.newton_D(A_gamma[0], A_gamma[1], xp)
    d_token: uint256 = token_supply * D / D0 - token_supply
    d_token -= self._calc_token_fee(amountsp, xp) * d_token / 10**10 + 1
    return d_token


@internal
@view
def _calc_withdraw_one_coin(A_gamma: uint256[2], token_amount: uint256, i: uint256, update_D: bool,
                            calc_price: bool) -> (uint256, uint256, uint256, uint256[N_COINS]):
    token_supply: uint256 = CurveToken(token).totalSupply()
    assert token_amount <= token_supply  # dev: token amount more than supply
    assert i < N_COINS  # dev: coin out of range

    xx: uint256[N_COINS] = self.balances
    D0: uint256 = 0

    price_scale_i: uint256 = self.price_scale * PRECISIONS[1]
    xp: uint256[N_COINS] = [xx[0] * PRECISIONS[0], xx[1] * price_scale_i / PRECISION]
    if i == 0:
        price_scale_i = PRECISION * PRECISIONS[0]

    if update_D:
        D0 = self.newton_D(A_gamma[0], A_gamma[1], xp)
    else:
        D0 = self.D

    D: uint256 = D0

    # Charge the fee on D, not on y, e.g. reducing invariant LESS than charging the user
    fee: uint256 = self._fee(xp)
    dD: uint256 = token_amount * D / token_supply
    D -= (dD - (fee * dD / (2 * 10**10) + 1))
    y: uint256 = self.newton_y(A_gamma[0], A_gamma[1], xp, D, i)
    dy: uint256 = (xp[i] - y) * PRECISION / price_scale_i
    xp[i] = y

    # Price calc
    p: uint256 = 0
    if calc_price and dy > 10**5 and token_amount > 10**5:
        # p_i = dD / D0 * sum'(p_k * x_k) / (dy - dD / D0 * y0)
        S: uint256 = 0
        precision: uint256 = PRECISIONS[0]
        if i == 1:
            S = xx[0] * PRECISIONS[0]
            precision = PRECISIONS[1]
        else:
            S = xx[1] * PRECISIONS[1]
        S = S * dD / D0
        p = S * PRECISION / (dy * precision - dD * xx[i] * precision / D0)
        if i == 0:
            p = (10**18)**2 / p

    return dy, p, D, xp


@view
@external
def calc_withdraw_one_coin(token_amount: uint256, i: uint256) -> uint256:
    return self._calc_withdraw_one_coin(self._A_gamma(), token_amount, i, True, False)[0]


@external
@nonreentrant('lock')
def remove_liquidity_one_coin(token_amount: uint256, i: uint256, min_amount: uint256, use_eth: bool = False) -> uint256:
    assert not self.is_killed  # dev: the pool is killed

    A_gamma: uint256[2] = self._A_gamma()

    dy: uint256 = 0
    D: uint256 = 0
    p: uint256 = 0
    xp: uint256[N_COINS] = empty(uint256[N_COINS])
    future_A_gamma_time: uint256 = self.future_A_gamma_time
    dy, p, D, xp = self._calc_withdraw_one_coin(A_gamma, token_amount, i, (future_A_gamma_time > 0), True)
    assert dy >= min_amount, "Slippage"

    if block.timestamp >= future_A_gamma_time:
        self.future_A_gamma_time = 1

    self.balances[i] -= dy
    CurveToken(token).burnFrom(msg.sender, token_amount)

    _coins: address[N_COINS] = coins
    if use_eth and i == ETH_INDEX:
        raw_call(msg.sender, b"", value=dy)
    else:
        if i == ETH_INDEX:
            WETH(_coins[i]).deposit(value=dy)
        assert ERC20(_coins[i]).transfer(msg.sender, dy)

    self.tweak_price(A_gamma, xp, p, D)

    log RemoveLiquidityOne(msg.sender, token_amount, i, dy)

    return dy


@external
@nonreentrant('lock')
def claim_admin_fees():
    self._claim_admin_fees()


# Admin parameters
@external
def ramp_A_gamma(future_A: uint256, future_gamma: uint256, future_time: uint256):
    assert msg.sender == self.owner  # dev: only owner
    assert block.timestamp > self.initial_A_gamma_time + (MIN_RAMP_TIME-1)
    assert future_time > block.timestamp + (MIN_RAMP_TIME-1)  # dev: insufficient time

    A_gamma: uint256[2] = self._A_gamma()
    initial_A_gamma: uint256 = shift(A_gamma[0], 128)
    initial_A_gamma = bitwise_or(initial_A_gamma, A_gamma[1])

    assert future_A > MIN_A-1
    assert future_A < MAX_A+1
    assert future_gamma > MIN_GAMMA-1
    assert future_gamma < MAX_GAMMA+1

    ratio: uint256 = 10**18 * future_A / A_gamma[0]
    assert ratio < 10**18 * MAX_A_CHANGE + 1
    assert ratio > 10**18 / MAX_A_CHANGE - 1

    ratio = 10**18 * future_gamma / A_gamma[1]
    assert ratio < 10**18 * MAX_A_CHANGE + 1
    assert ratio > 10**18 / MAX_A_CHANGE - 1

    self.initial_A_gamma = initial_A_gamma
    self.initial_A_gamma_time = block.timestamp

    future_A_gamma: uint256 = shift(future_A, 128)
    future_A_gamma = bitwise_or(future_A_gamma, future_gamma)
    self.future_A_gamma_time = future_time
    self.future_A_gamma = future_A_gamma

    log RampAgamma(A_gamma[0], future_A, A_gamma[1], future_gamma, block.timestamp, future_time)


@external
def stop_ramp_A_gamma():
    assert msg.sender == self.owner  # dev: only owner

    A_gamma: uint256[2] = self._A_gamma()
    current_A_gamma: uint256 = shift(A_gamma[0], 128)
    current_A_gamma = bitwise_or(current_A_gamma, A_gamma[1])
    self.initial_A_gamma = current_A_gamma
    self.future_A_gamma = current_A_gamma
    self.initial_A_gamma_time = block.timestamp
    self.future_A_gamma_time = block.timestamp
    # now (block.timestamp < t1) is always False, so we return saved A

    log StopRampA(A_gamma[0], A_gamma[1], block.timestamp)


@external
def commit_new_parameters(
    _new_mid_fee: uint256,
    _new_out_fee: uint256,
    _new_admin_fee: uint256,
    _new_fee_gamma: uint256,
    _new_allowed_extra_profit: uint256,
    _new_adjustment_step: uint256,
    _new_ma_half_time: uint256,
    ):
    assert msg.sender == self.owner  # dev: only owner
    assert self.admin_actions_deadline == 0  # dev: active action

    new_mid_fee: uint256 = _new_mid_fee
    new_out_fee: uint256 = _new_out_fee
    new_admin_fee: uint256 = _new_admin_fee
    new_fee_gamma: uint256 = _new_fee_gamma
    new_allowed_extra_profit: uint256 = _new_allowed_extra_profit
    new_adjustment_step: uint256 = _new_adjustment_step
    new_ma_half_time: uint256 = _new_ma_half_time

    # Fees
    if new_out_fee < MAX_FEE+1:
        assert new_out_fee > MIN_FEE-1  # dev: fee is out of range
    else:
        new_out_fee = self.out_fee
    if new_mid_fee > MAX_FEE:
        new_mid_fee = self.mid_fee
    assert new_mid_fee <= new_out_fee  # dev: mid-fee is too high
    if new_admin_fee > MAX_ADMIN_FEE:
        new_admin_fee = self.admin_fee

    # AMM parameters
    if new_fee_gamma < 10**18:
        assert new_fee_gamma > 0  # dev: fee_gamma out of range [1 .. 10**18]
    else:
        new_fee_gamma = self.fee_gamma
    if new_allowed_extra_profit > 10**18:
        new_allowed_extra_profit = self.allowed_extra_profit
    if new_adjustment_step > 10**18:
        new_adjustment_step = self.adjustment_step

    # MA
    if new_ma_half_time < 7*86400:
        assert new_ma_half_time > 0  # dev: MA time should be longer than 1 second
    else:
        new_ma_half_time = self.ma_half_time

    _deadline: uint256 = block.timestamp + ADMIN_ACTIONS_DELAY
    self.admin_actions_deadline = _deadline

    self.future_admin_fee = new_admin_fee
    self.future_mid_fee = new_mid_fee
    self.future_out_fee = new_out_fee
    self.future_fee_gamma = new_fee_gamma
    self.future_allowed_extra_profit = new_allowed_extra_profit
    self.future_adjustment_step = new_adjustment_step
    self.future_ma_half_time = new_ma_half_time

    log CommitNewParameters(_deadline, new_admin_fee, new_mid_fee, new_out_fee,
                            new_fee_gamma,
                            new_allowed_extra_profit, new_adjustment_step,
                            new_ma_half_time)


@external
@nonreentrant('lock')
def apply_new_parameters():
    assert msg.sender == self.owner  # dev: only owner
    assert block.timestamp >= self.admin_actions_deadline  # dev: insufficient time
    assert self.admin_actions_deadline != 0  # dev: no active action

    self.admin_actions_deadline = 0

    admin_fee: uint256 = self.future_admin_fee
    if self.admin_fee != admin_fee:
        self._claim_admin_fees()
        self.admin_fee = admin_fee

    mid_fee: uint256 = self.future_mid_fee
    self.mid_fee = mid_fee
    out_fee: uint256 = self.future_out_fee
    self.out_fee = out_fee
    fee_gamma: uint256 = self.future_fee_gamma
    self.fee_gamma = fee_gamma
    allowed_extra_profit: uint256 = self.future_allowed_extra_profit
    self.allowed_extra_profit = allowed_extra_profit
    adjustment_step: uint256 = self.future_adjustment_step
    self.adjustment_step = adjustment_step
    ma_half_time: uint256 = self.future_ma_half_time
    self.ma_half_time = ma_half_time

    log NewParameters(admin_fee, mid_fee, out_fee,
                      fee_gamma,
                      allowed_extra_profit, adjustment_step,
                      ma_half_time)


@external
def revert_new_parameters():
    assert msg.sender == self.owner  # dev: only owner

    self.admin_actions_deadline = 0


@external
def commit_transfer_ownership(_owner: address):
    assert msg.sender == self.owner  # dev: only owner
    assert self.transfer_ownership_deadline == 0  # dev: active transfer

    _deadline: uint256 = block.timestamp + ADMIN_ACTIONS_DELAY
    self.transfer_ownership_deadline = _deadline
    self.future_owner = _owner

    log CommitNewAdmin(_deadline, _owner)


@external
def apply_transfer_ownership():
    assert msg.sender == self.owner  # dev: only owner
    assert block.timestamp >= self.transfer_ownership_deadline  # dev: insufficient time
    assert self.transfer_ownership_deadline != 0  # dev: no active transfer

    self.transfer_ownership_deadline = 0
    _owner: address = self.future_owner
    self.owner = _owner

    log NewAdmin(_owner)


@external
def revert_transfer_ownership():
    assert msg.sender == self.owner  # dev: only owner

    self.transfer_ownership_deadline = 0


@external
def kill_me():
    assert msg.sender == self.owner  # dev: only owner
    assert self.kill_deadline > block.timestamp  # dev: deadline has passed
    self.is_killed = True


@external
def unkill_me():
    assert msg.sender == self.owner  # dev: only owner
    self.is_killed = False


@external
def set_admin_fee_receiver(_admin_fee_receiver: address):
    assert msg.sender == self.owner  # dev: only owner
    self.admin_fee_receiver = _admin_fee_receiver


@internal
@pure
def sqrt_int(x: uint256) -> uint256:
    """
    Originating from: https://github.com/vyperlang/vyper/issues/1266
    """

    if x == 0:
        return 0

    z: uint256 = (x + 10**18) / 2
    y: uint256 = x

    for i in range(256):
        if z == y:
            return y
        y = z
        z = (x * 10**18 / z + z) / 2

    raise "Did not converge"


@external
@view
def lp_price() -> uint256:
    """
    Approximate LP token price
    """
    max_price: uint256 = 2 * self.virtual_price * self.sqrt_int(self.price_oracle) / 10**18

    return max_price

Contract Security Audit

Contract ABI

[{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"uint256","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"uint256","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[2]","indexed":false},{"name":"fee","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[2]","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amount","type":"uint256","indexed":false},{"name":"coin_index","type":"uint256","indexed":false},{"name":"coin_amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"CommitNewAdmin","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"admin","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"NewAdmin","inputs":[{"name":"admin","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"CommitNewParameters","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"admin_fee","type":"uint256","indexed":false},{"name":"mid_fee","type":"uint256","indexed":false},{"name":"out_fee","type":"uint256","indexed":false},{"name":"fee_gamma","type":"uint256","indexed":false},{"name":"allowed_extra_profit","type":"uint256","indexed":false},{"name":"adjustment_step","type":"uint256","indexed":false},{"name":"ma_half_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewParameters","inputs":[{"name":"admin_fee","type":"uint256","indexed":false},{"name":"mid_fee","type":"uint256","indexed":false},{"name":"out_fee","type":"uint256","indexed":false},{"name":"fee_gamma","type":"uint256","indexed":false},{"name":"allowed_extra_profit","type":"uint256","indexed":false},{"name":"adjustment_step","type":"uint256","indexed":false},{"name":"ma_half_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampAgamma","inputs":[{"name":"initial_A","type":"uint256","indexed":false},{"name":"future_A","type":"uint256","indexed":false},{"name":"initial_gamma","type":"uint256","indexed":false},{"name":"future_gamma","type":"uint256","indexed":false},{"name":"initial_time","type":"uint256","indexed":false},{"name":"future_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"name":"current_A","type":"uint256","indexed":false},{"name":"current_gamma","type":"uint256","indexed":false},{"name":"time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"ClaimAdminFee","inputs":[{"name":"admin","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"owner","type":"address"},{"name":"admin_fee_receiver","type":"address"},{"name":"A","type":"uint256"},{"name":"gamma","type":"uint256"},{"name":"mid_fee","type":"uint256"},{"name":"out_fee","type":"uint256"},{"name":"allowed_extra_profit","type":"uint256"},{"name":"fee_gamma","type":"uint256"},{"name":"adjustment_step","type":"uint256"},{"name":"admin_fee","type":"uint256"},{"name":"ma_half_time","type":"uint256"},{"name":"initial_price","type":"uint256"},{"name":"_token","type":"address"},{"name":"_coins","type":"address[2]"}],"outputs":[]},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"view","type":"function","name":"token","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"exchange_underlying","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"add_liquidity","inputs":[{"name":"amounts","type":"uint256[2]"},{"name":"min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"payable","type":"function","name":"add_liquidity","inputs":[{"name":"amounts","type":"uint256[2]"},{"name":"min_mint_amount","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"min_amounts","type":"uint256[2]"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"min_amounts","type":"uint256[2]"},{"name":"use_eth","type":"bool"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"amounts","type":"uint256[2]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"},{"name":"min_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"token_amount","type":"uint256"},{"name":"i","type":"uint256"},{"name":"min_amount","type":"uint256"},{"name":"use_eth","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_admin_fees","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"ramp_A_gamma","inputs":[{"name":"future_A","type":"uint256"},{"name":"future_gamma","type":"uint256"},{"name":"future_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A_gamma","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"commit_new_parameters","inputs":[{"name":"_new_mid_fee","type":"uint256"},{"name":"_new_out_fee","type":"uint256"},{"name":"_new_admin_fee","type":"uint256"},{"name":"_new_fee_gamma","type":"uint256"},{"name":"_new_allowed_extra_profit","type":"uint256"},{"name":"_new_adjustment_step","type":"uint256"},{"name":"_new_ma_half_time","type":"uint256"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"apply_new_parameters","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revert_new_parameters","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"commit_transfer_ownership","inputs":[{"name":"_owner","type":"address"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"apply_transfer_ownership","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"revert_transfer_ownership","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"kill_me","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"unkill_me","inputs":[],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"set_admin_fee_receiver","inputs":[{"name":"_admin_fee_receiver","type":"address"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"lp_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_scale","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"price_oracle","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"last_prices","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"last_prices_timestamp","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"initial_A_gamma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_A_gamma_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"allowed_extra_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_allowed_extra_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"fee_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_fee_gamma","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"adjustment_step","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_adjustment_step","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"ma_half_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_ma_half_time","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"mid_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"out_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_mid_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_out_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"future_admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"D","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"future_owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"xcp_profit","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"xcp_profit_a","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"is_killed","inputs":[],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"kill_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"transfer_ownership_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_actions_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"admin_fee_receiver","inputs":[],"outputs":[{"name":"","type":"address"}]}]

6020615b206080396080518060a01c615b1b5760e05260206020615b20016080396080518060a01c615b1b57610100526020610180615b20016080396080518060a01c615b1b57610120526101a0615b20016020816080396080518060a01c615b1b57610140526020602082016080396080518060a01c615b1b57610160525060e051601a5560206040615b200160803960805160801b6101805260206060615b2001608039608051610180511761018052610180516005556101805160065560206080615b2001608039608051601155602060a0615b2001608039608051601255602060c0615b2001608039608051600955602060e0615b2001608039608051600b556020610100615b2001608039608051600d556020610120615b20016080396080516013556020610160615b20016080396080516001556020610160615b20016080396080516002556020610160615b2001608039608051600355426004556020610140615b2001608039608051600f55670de0b6b3a7640000601d5542624f1a008181830110615b1b578082019050905060215561010051602455610120516101a052610140516101c052610160516101e052604e601263313ce567610200526020610200600461021c610140515afa6101e2573d600060003e3d6000fd5b601f3d1115615b1b5761020051808210615b1b57808203905090501015615b1b57601263313ce567610200526020610200600461021c610140515afa61022d573d600060003e3d6000fd5b601f3d1115615b1b5761020051808210615b1b5780820390509050600a0a61028052604e601263313ce567610240526020610240600461025c610160515afa61027b573d600060003e3d6000fd5b601f3d1115615b1b5761024051808210615b1b57808203905090501015615b1b57601263313ce567610240526020610240600461025c610160515afa6102c6573d600060003e3d6000fd5b601f3d1115615b1b5761024051808210615b1b5780820390509050600a0a6102a052615ac956600436101561000d57612499565b60046000601c37600051635b41b908811861002d576000610cc052610048565b63394747c5811861008d576084358060011c6157d757610cc0525b6000546157d7576001600055336109a052346109c052608060046109e037610cc051610a6052610079610ce0614743565b610ce051610d00526020610d006000600055f35b6365b2489b81186100db576000546157d7576001600055336109a052346109c052608060046109e0376001610a60526100c7610cc0614743565b610cc051610ce0526020610ce06000600055f35b630b4c7e4d81186100f15760006109a05261010c565b63ee22be238118610a58576064358060011c6157d7576109a0525b6000546157d75760016000556020546157d75760006004351161013457600060243511610137565b60015b156157d757610147610a0061386d565b610a0080516109c05280602001516109e0525060803803602081608039608051610a0052602081602001608039608051610a205250601754610a4052601854610a605260e036610a8037610a4051610b6052610a6051610b8052610ba060006002818352015b610a40610ba05160028110156157d75760200201516020610ba051026004013581818301106157d75780820190509050610bc052610bc051610a40610ba05160028110156157d7576020020152610bc0516001610ba05160028110156157d757026017015581516001018083528114156101ad575050610a4051610ac052610a6051610ae0526001546020604038036020016080396080518082028215828483041417156157d75790509050610ba052610a40516020604038036080396080518082028215828483041417156157d75790509050610a4052610a6051610ba0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610a6052610b60516020604038036080396080518082028215828483041417156157d75790509050610b6052610b8051610ba0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610b80526109a05161031b57346157d7575b610bc060006002818352015b6109a05161033657600061033c565b610bc051155b15610353576020610bc051026004013534186157d7575b60006020610bc051026004013511156104a4576109a0511561037c576000610bc051141561037f565b60015b15610456576323b872dd610be05233610c005230610c20526020610bc0510260040135610c40526020610be06064610bfc6000610a00610bc05160028110156157d75760200201515af16103d8573d600060003e3d6000fd5b601f3d11156157d757610be051156157d757610bc05161045657632e1a7d4d610be0526020610bc0510260040135610c0052610a00610bc05160028110156157d75760200201513b156157d757600060006024610bfc6000610a00610bc05160028110156157d75760200201515af1610456573d600060003e3d6000fd5b610a40610bc05160028110156157d7576020020151610b60610bc05160028110156157d75760200201518082106157d75780820390509050610a80610bc05160028110156157d75760200201525b8151600101808352811415610327575050600854610bc0526000610bc051116104d357601954610b4052610516565b6109c051610200526109e05161022052610b605161024052610b8051610260526104fe610be0612666565b610be051610b4052610bc05142106105165760016008555b6109c051610200526109e05161022052610a405161024052610a605161026052610541610c00612666565b610c0051610be0526318160ddd610c20526020610c206004610c3c602060a038036080396080515afa610579573d600060003e3d6000fd5b601f3d11156157d757610c2051610c00526000610b4051116105b557610be051610200526105a8610c20613b2b565b610c2051610b00526105f9565b610c0051610be0518082028215828483041417156157d75790509050610b40518080156157d757820490509050610c00518082106157d75780820390509050610b00525b6000610b005111156157d7576000610b40511161068057610be051601955670de0b6b3a7640000601e55670de0b6b3a7640000601c556340c10f19610c205233610c4052610b0051610c60526020610c206044610c3c6000602060a038036080396080515af161066e573d600060003e3d6000fd5b601f3d11156157d757610c205061097a565b610a805161016052610aa05161018052610a40516101a052610a60516101c0526106ab610c2061501c565b610c2051610b00518082028215828483041417156157d757905090506402540be40080820490509050600181818301106157d75780820190509050610b2052610b008051610b20518082106157d75780820390509050815250610c008051610b005181818301106157d757808201905090508152506340c10f19610c205233610c4052610b0051610c60526020610c206044610c3c6000602060a038036080396080515af161075f573d600060003e3d6000fd5b601f3d11156157d757610c20506000610c2052620186a0610b0051111561094257600435156107915760243515610794565b60015b1561094257606036610c4037600435156107e857610ae0516020604038036020016080396080518082028215828483041417156157d75790509050610c4052602060403803608039608051610c605261082a565b610ac0516020604038036080396080518082028215828483041417156157d75790509050610c4052602060403803602001608039608051610c60526001610c80525b610c4051610b00518082028215828483041417156157d75790509050610c00518080156157d757820490509050610c4052610c4051670de0b6b3a76400008082028215828483041417156157d757905090506020610c80510260040135610c60518082028215828483041417156157d75790509050610b0051610ac0610c805160028110156157d75760200201518082028215828483041417156157d75790509050610c60518082028215828483041417156157d75790509050610c00518080156157d7578204905090508082106157d757808203905090508080156157d757820490509050610c2052610c8051610942576ec097ce7bc90715b34b9f1000000000610c20518080156157d757820490509050610c20525b6109c0516106a0526109e0516106c052610a40516106e052610a605161070052610c205161072052610be0516107405261097a613f35565b604435610b005110156109fe576008610c20527f536c697070616765000000000000000000000000000000000000000000000000610c4052610c2050610c205180610c4001818260206001820306601f82010390500336823750506308c379a0610be0526020610c0052610c205160206001820306601f8201039050604401610bfcfd5b337f540ab385f9b5d450a27404172caade516b3ba3f4be88239ac56a2ad1de2a1f5a600435610c2052602435610c4052610b2051610c6052610c0051610c80526080610c20a2610b0051610c20526020610c206000600055f35b63fc0c546a8118610a7d57346157d757602060a0380360803960805160e052602060e0f35b63c66106578118610acc57346157d7576080380360208160803960805160e052602081602001608039608051610100525060e060043560028110156157d7576020020151610120526020610120f35b63f446c1d08118610af657346157d757610ae76101c061386d565b6101c051610200526020610200f35b63b13739298118610b2357346157d757610b116101c061386d565b6101c060200151610200526020610200f35b63ddca3f438118610b7a57346157d757610b3e6101606137f3565b61016080516101c05280602001516101e052506101c05160e0526101e05161010052610b6b6101a06139e0565b6101a051610200526020610200f35b63bb7b8b808118610c1257346157d757670de0b6b3a764000060195461020052610ba5610280613b2b565b610280518082028215828483041417156157d757905090506318160ddd6102a05260206102a060046102bc602060a038036080396080515afa610bed573d600060003e3d6000fd5b601f3d11156157d7576102a0518080156157d7578204905090506102e05260206102e0f35b63556d6e9f8118610ef257346157d757602435600435146157d757600260043510156157d757600260243510156157d7576001546020604038036020016080396080518082028215828483041417156157d757905090506104a0526017546104c0526018546104e052610c8661054061386d565b610540805161050052806020015161052052506019546105405260006008541115610d0d57610500516105c052610520516105e052610cc66105606137f3565b610560805161060052806020015161062052506105c051610200526105e0516102205261060051610240526106205161026052610d046105a0612666565b6105a051610540525b6104c060043560028110156157d75760200201805160443581818301106157d757808201905090508152506104c0516020604038036080396080518082028215828483041417156157d757905090506104c0526104e0516104a0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090506104e0526105005160e05261052051610100526104c051610120526104e05161014052610540516101605260243561018052610dc9610580612df5565b61058051610560526104c060243560028110156157d7576020020151610560518082106157d7578082039050905060018082106157d7578082039050905061058052610560516104c060243560028110156157d7576020020152600060243511610e535761058080516020604038036080396080518080156157d757820490509050815250610e8a565b61058051670de0b6b3a76400008082028215828483041417156157d757905090506104a0518080156157d757820490509050610580525b61058080516104c05160e0526104e05161010052610ea96105a06139e0565b6105a051610580518082028215828483041417156157d757905090506402540be400808204905090508082106157d75780820390509050815250610580516105a05260206105a0f35b635b36389c8118610f0757600060e052610f21565b63269b5581811861126e576064358060011c6157d75760e0525b346157d7576000546157d7576001600055608038036020816080396080516101005260208160200160803960805161012052506318160ddd610160526020610160600461017c602060a038036080396080515afa610f84573d600060003e3d6000fd5b601f3d11156157d75761016051610140526379cc67906101605233610180526004356101a0526020610160604461017c6000602060a038036080396080515af1610fd3573d600060003e3d6000fd5b601f3d11156157d75761016050601754610160526018546101805260043560018082106157d757808203905090506101a0526101c060006002818352015b6101606101c05160028110156157d75760200201516101a0518082028215828483041417156157d75790509050610140518080156157d7578204905090506101e05260206101c05102602401356101e051106157d7576101606101c05160028110156157d75760200201516101e0518082106157d7578082039050905060016101c05160028110156157d75702601701556101e0516101606101c05160028110156157d757602002015260e0516110c95760006110cf565b6101c051155b611191576101c0516111325763d0e30db0610200526101006101c05160028110156157d75760200201513b156157d75760006000600461021c6101e0516101006101c05160028110156157d75760200201515af1611132573d600060003e3d6000fd5b63a9059cbb6102005233610220526101e051610240526020610200604461021c60006101006101c05160028110156157d75760200201515af161117a573d600060003e3d6000fd5b601f3d11156157d75761020051156157d7576111bc565b6000610200526102005060006000610200516102206101e051335af16111bc573d600060003e3d6000fd5b81516001018083528114156110115750506019546101c0526101c0516101c0516101a0518082028215828483041417156157d75790509050610140518080156157d7578204905090508082106157d75780820390509050601955337fdd3c0336a16f1b64f172b7bb0dad5b2b3c7c76f91e8c4aafd6aae60dce800153610160516101e0526101805161020052610140516004358082106157d757808203905090506102205260606101e0a26000600055005b638d8ea72781186114fa57346157d7576318160ddd6104c05260206104c060046104dc602060a038036080396080515afa6112ae573d600060003e3d6000fd5b601f3d11156157d7576104c0516104a0526001546020604038036020016080396080518082028215828483041417156157d757905090506104c0526112f461052061386d565b61052080516104e052806020015161050052506113126105606137f3565b610560805161052052806020015161054052506004356020604038036080396080518082028215828483041417156157d75790509050610560526024356104c0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610580526019546105a052600060085411156113c1576104e051610200526105005161022052610520516102405261054051610260526113b86105c0612666565b6105c0516105a0525b61052080516105605181818301106157d7578082019050905081525061054080516105805181818301106157d757808201905090508152506104e051610200526105005161022052610520516102405261054051610260526114246105e0612666565b6105e0516105c0526104a0516105c0518082028215828483041417156157d757905090506105a0518080156157d7578204905090506104a0518082106157d757808203905090506105e0526105e0805161056051610160526105805161018052610520516101a052610540516101c05261149f61060061501c565b610600516105e0518082028215828483041417156157d757905090506402540be40080820490509050600181818301106157d757808201905090508082106157d757808203905090508152506105e051610600526020610600f35b634fb08c5e811861158657346157d75761151561074061386d565b61074080516108205280602001516108405250604060046108603760016108a05260006108c052610820516104a052610840516104c052610860516104e05261088051610500526108a051610520526108c051610540526115776107806151a5565b610780516108e05260206108e0f35b63f1dc3cc9811861159c5760006109a0526115b7565b638f15b6b5811861190a576064358060011c6157d7576109a0525b346157d7576000546157d75760016000556020546157d7576115da610a0061386d565b610a0080516109c05280602001516109e0525060a036610a0037600854610aa0526109c0516104a0526109e0516104c052604060046104e0376000610aa051116105205260016105405261162f610ac06151a5565b610ac08051610a00526020810151610a40526040810151610a2052606081018051610a60528060200151610a80525050604435610a005110156116e3576008610ac0527f536c697070616765000000000000000000000000000000000000000000000000610ae052610ac050610ac05180610ae001818260206001820306601f82010390500336823750506308c379a0610a80526020610aa052610ac05160206001820306601f8201039050604401610a9cfd5b610aa05142106116f35760016008555b600160243560028110156157d757026017018054610a00518082106157d757808203905090508155506379cc6790610ac05233610ae052600435610b00526020610ac06044610adc6000602060a038036080396080515af161175a573d600060003e3d6000fd5b601f3d11156157d757610ac05060803803602081608039608051610ac052602081602001608039608051610ae052506109a05161179857600061179d565b602435155b61185b576024356117fd5763d0e30db0610b0052610ac060243560028110156157d75760200201513b156157d757600060006004610b1c610a0051610ac060243560028110156157d75760200201515af16117fd573d600060003e3d6000fd5b63a9059cbb610b005233610b2052610a0051610b40526020610b006044610b1c6000610ac060243560028110156157d75760200201515af1611844573d600060003e3d6000fd5b601f3d11156157d757610b0051156157d757611886565b6000610b0052610b005060006000610b0051610b20610a0051335af1611886573d600060003e3d6000fd5b6109c0516106a0526109e0516106c052610a60516106e052610a805161070052610a405161072052610a2051610740526118be613f35565b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a060406004610b0037610a0051610b40526060610b00a2610a0051610b00526020610b006000600055f35b63c93f49e8811861193557346157d7576000546157d757600160005561192e613bb0565b6000600055005b635e2480728118611b3157346157d757601a5433186157d7576007546201517f81818301106157d757808201905090504211156157d757426201517f81818301106157d7578082019050905060443511156157d75761199561020061386d565b61020080516101c05280602001516101e052506101c05160801b610200526101e051610200511761020052610f9f60043511156157d75763ee6b280160043510156157d7576402540be3ff60243511156157d75766470de4df82000160243510156157d757670de0b6b3a76400006004358082028215828483041417156157d757905090506101c0518080156157d75782049050905061022052678ac7230489e800016102205110156157d75767016345785d89ffff6102205111156157d757670de0b6b3a76400006024358082028215828483041417156157d757905090506101e0518080156157d75782049050905061022052678ac7230489e800016102205110156157d75767016345785d89ffff6102205111156157d757610200516005554260075560043560801b61024052602435610240511761024052604435600855610240516006557fe35f0559b0642164e286b30df2077ec3a05426617a25db7578fd20ba39a6cd056101c05161026052600435610280526101e0516102a0526024356102c052426102e0526044356103005260c0610260a1005b63244c7c2e8118611bd457346157d757601a5433186157d757611b5561020061386d565b61020080516101c05280602001516101e052506101c05160801b610200526101e051610200511761020052610200516005556102005160065542600755426008557f5f0e7fba3d100c9e19446e1c92fe436f0a9a22fe99669360e4fdd6d3de2fc2846101c051610220526101e0516102405242610260526060610220a1005b63a43c33518118611d9a57346157d757601a5433186157d7576023546157d75760e0600460e0376402540be4016101005110611c165760125461010052611c25565b6207a11f6101005111156157d7575b6402540be40060e0511115611c3b5760115460e0525b6101005160e051116157d7576402540be400610120511115611c5f57601354610120525b670de0b6b3a76400006101405110611c7d57600b5461014052611c8a565b60006101405111156157d7575b670de0b6b3a7640000610160511115611ca557600954610160525b670de0b6b3a7640000610180511115611cc057600d54610180525b62093a806101a05110611cd957600f546101a052611ce6565b60006101a05111156157d7575b426203f48081818301106157d757808201905090506101c0526101c0516023556101205160165560e0516014556101005160155561014051600c5561016051600a5561018051600e556101a0516010556101c0517f913fde9a37e1f8ab67876a4d0ce80790d764fcfc5692f4529526df9c6bdde553610120516101e05260e0516102005261010051610220526101405161024052610160516102605261018051610280526101a0516102a05260e06101e0a2005b632a7dd7cd8118611eb457346157d7576000546157d7576001600055601a5433186157d75760235442106157d7576000602354146157d75760006023556016546106a0526106a05160135414611dfa57611df2613bb0565b6106a0516013555b6014546106c0526106c0516011556015546106e0526106e051601255600c546107005261070051600b55600a546107205261072051600955600e546107405261074051600d556010546107605261076051600f557f1c65bbdc939f346e5d6f0bde1f072819947438d4fc7b182cc59c2f6dc55040876106a051610780526106c0516107a0526106e0516107c052610700516107e05261072051610800526107405161082052610760516108405260e0610780a16000600055005b63226840fb8118611ed457346157d757601a5433186157d7576000602355005b636b441a408118611f58576004358060a01c6157d75760e052346157d757601a5433186157d7576022546157d757426203f48081818301106157d75780820190509050610100526101005160225560e051601b5560e051610100517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb9356000610120a3005b636a1c05ae8118611fc157346157d757601a5433186157d75760225442106157d7576000602254146157d7576000602255601b5460e05260e051601a5560e0517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c6000610100a2005b6386fbf1938118611fe157346157d757601a5433186157d7576000602255005b63e3698853811861200b57346157d757601a5433186157d7574260215411156157d7576001602055005b633046f972811861202b57346157d757601a5433186157d7576000602055005b637242e524811861205a576004358060a01c6157d75760e052346157d757601a5433186157d75760e051602455005b6354f0f7d581186120cf57346157d7576002601e548082028215828483041417156157d7579050905060025460e0526120946101a061568a565b6101a0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061018052610180516101a05260206101a0f35b63b9e8c9fd81186120eb57346157d75760015460e052602060e0f35b6386fc88d3811861210757346157d75760025460e052602060e0f35b63c146bf94811861212357346157d75760035460e052602060e0f35b636112c747811861213f57346157d75760045460e052602060e0f35b63204fe3d5811861215b57346157d75760055460e052602060e0f35b63f30cfad5811861217757346157d75760065460e052602060e0f35b63e89876ff811861219357346157d75760075460e052602060e0f35b63f9ed959781186121af57346157d75760085460e052602060e0f35b6349fe9e7781186121cb57346157d75760095460e052602060e0f35b63727ced5781186121e757346157d757600a5460e052602060e0f35b6372d4f0e2811861220357346157d757600b5460e052602060e0f35b63d7c3dcbe811861221f57346157d757600c5460e052602060e0f35b63083812e5811861223b57346157d757600d5460e052602060e0f35b634ea12c7d811861225757346157d757600e5460e052602060e0f35b63662b6274811861227357346157d757600f5460e052602060e0f35b630c5e23d4811861228f57346157d75760105460e052602060e0f35b6392526c0c81186122ab57346157d75760115460e052602060e0f35b63ee8de67581186122c757346157d75760125460e052602060e0f35b63fee3f7f981186122e357346157d75760135460e052602060e0f35b637cf9aedc81186122ff57346157d75760145460e052602060e0f35b637d1b060c811861231b57346157d75760155460e052602060e0f35b63e3824462811861233757346157d75760165460e052602060e0f35b634903b0d1811861236357346157d757600160043560028110156157d757026017015460e052602060e0f35b630f529ba2811861237f57346157d75760195460e052602060e0f35b638da5cb5b811861239b57346157d757601a5460e052602060e0f35b631ec0cdc181186123b757346157d757601b5460e052602060e0f35b637ba1a74d81186123d357346157d757601c5460e052602060e0f35b630b7b594b81186123ef57346157d757601d5460e052602060e0f35b630c46b72a811861240b57346157d757601e5460e052602060e0f35b639c868ac0811861242757346157d75760205460e052602060e0f35b632a426896811861244357346157d75760215460e052602060e0f35b63e0a0b586811861245f57346157d75760225460e052602060e0f35b63405e28f8811861247b57346157d75760235460e052602060e0f35b636e42e4d2811861249757346157d75760245460e052602060e0f35b505b005b60e051610140526101005161016052610120516124b95760006124c3565b6101605161014051105b156124d857610100516101405260e051610160525b610140516101805260006101a0526101c0600060ff818352015b610180516101e0526101805161014051610160518082028215828483041417156157d75790509050610180518080156157d75782049050905081818301106157d75780820190509050600280820490509050610180526101e0516101805111612574576101e051610180518082106157d757808203905090506101a05261258f565b610180516101e0518082106157d757808203905090506101a0525b60016101a05111156125c657610180516101a051670de0b6b3a76400008082028215828483041417156157d75790509050106125c9565b60015b156125dc57505061018051815250612664565b81516001018083528114156124f257505060106101c0527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101e0526101c0506101c051806101e001818260206001820306601f82010390500336823750506308c379a06101805260206101a0526101c05160206001820306601f820103905060440161019cfd5b565b610f9f6102005111612679576000612684565b63ee6b280161020051105b156157d7576402540be3ff610220511161269f5760006126ad565b66470de4df82000161022051105b156157d7576102405161028052610260516102a0526102a0516102805110156126e1576102605161028052610240516102a0525b633b9ac9ff61028051116126f657600061270b565b6d314dc6448d9338c15b0a0000000161028051105b156157d757655af3107a3fff6102a051670de0b6b3a76400008082028215828483041417156157d75790509050610280518080156157d75782049050905011156157d75760026102805160e0526102a051610100526000610120526127716102e061249b565b6102e0518082028215828483041417156157d757905090506102c052610280516102a05181818301106157d757808201905090506102e052610300600060ff818352015b6102c05161032052673782dace9d900000610280518082028215828483041417156157d757905090506102c0518080156157d7578204905090506102a0518082028215828483041417156157d757905090506102c0518080156157d7578204905090506103405261022051670de0b6b3a764000081818301106157d757808201905090506103605261034051610360511161287b5761034051610360518082106157d75780820390509050600181818301106157d75780820190509050610360526128a8565b61036051610340518082106157d75780820390509050600181818301106157d75780820190509050610360525b670de0b6b3a76400006102c0518082028215828483041417156157d75790509050610220518080156157d757820490509050610360518082028215828483041417156157d75790509050610220518080156157d757820490509050610360518082028215828483041417156157d757905090506127108082028215828483041417156157d75790509050610200518080156157d75782049050905061038052673782dace9d900000610340518082028215828483041417156157d75790509050610360518080156157d7578204905090506103a0526102e0516102e0516103a0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905081818301106157d757808201905090506103805160028082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090506103a0516102c0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508082106157d757808203905090506103c0526102c0516103c0516102e05181818301106157d757808201905090508082028215828483041417156157d757905090506103c0518080156157d7578204905090506103e0526102c0516102c0518082028215828483041417156157d757905090506103c0518080156157d7578204905090506104005261034051670de0b6b3a764000011612b565761040080516102c051610380516103c0518080156157d7578204905090508082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061034051670de0b6b3a76400008082106157d757808203905090508082028215828483041417156157d75790509050610340518080156157d7578204905090508082106157d75780820390509050815250612bec565b61040080516102c051610380516103c0518080156157d7578204905090508082028215828483041417156157d75790509050670de0b6b3a764000080820490509050670de0b6b3a7640000610340518082106157d757808203905090508082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090508152505b610400516103e05111612c2157610400516103e0518082106157d757808203905090506002808204905090506102c052612c3c565b6103e051610400518082106157d757808203905090506102c0525b600061042052610320516102c05111612c6e57610320516102c0518082106157d7578082039050905061042052612c89565b6102c051610320518082106157d75780820390509050610420525b662386f26fc100006102c051808210612ca25781612ca4565b805b9050905061042051655af3107a40008082028215828483041417156157d757905090501015612d6b5761046060006002818352015b6020610460510261028001516104405261044051670de0b6b3a76400008082028215828483041417156157d757905090506102c0518080156157d75782049050905061048052662386f26fc0ffff6104805111612d37576000612d47565b68056bc75e2d6310000161048051105b156157d7578151600101808352811415612cd957505050506102c051815250612df3565b81516001018083528114156127b55750506010610300527f446964206e6f7420636f6e7665726765000000000000000000000000000000006103205261030050610300518061032001818260206001820306601f82010390500336823750506308c379a06102c05260206102e0526103005160206001820306601f82010390506044016102dcfd5b565b610f9f60e05111612e07576000612e11565b63ee6b280160e051105b156157d7576402540be3ff6101005111612e2c576000612e3a565b66470de4df82000161010051105b156157d75767016345785d89ffff6101605111612e58576000612e6d565b6d314dc6448d9338c15b0a0000000161016051105b156157d7576101206001610180518082106157d7578082039050905060028110156157d75760200201516101a0527001000000000000000000000000000000006101605110156157d7576002610160510a6101a05160048082028215828483041417156157d757905090508080156157d7578204905090506101c052671bc16d674ec800006101a0518082028215828483041417156157d75790509050610160518080156157d7578204905090506101e05266470de4df81ffff6101e05111612f37576000612f47565b680ad78ebc5ac62000016101e051105b156157d7576101a051655af3107a40008082049050905061016051655af3107a400080820490509050808210612f7d5781612f7f565b805b905090506064808210612f925781612f94565b805b9050905061020052610220600060ff818352015b6101c051610240526101e0516101c0518082028215828483041417156157d7579050905060028082028215828483041417156157d75790509050610160518080156157d757820490509050610260526101a0516101c05181818301106157d757808201905090506102805261010051670de0b6b3a764000081818301106157d757808201905090506102a052610260516102a0511161307257610260516102a0518082106157d75780820390509050600181818301106157d757808201905090506102a05261309f565b6102a051610260518082106157d75780820390509050600181818301106157d757808201905090506102a0525b670de0b6b3a7640000610160518082028215828483041417156157d75790509050610100518080156157d7578204905090506102a0518082028215828483041417156157d75790509050610100518080156157d7578204905090506102a0518082028215828483041417156157d757905090506127108082028215828483041417156157d7579050905060e0518080156157d7578204905090506102c052670de0b6b3a7640000671bc16d674ec80000610260518082028215828483041417156157d757905090506102a0518080156157d75782049050905081818301106157d757808201905090506102e052670de0b6b3a76400006101c0518082028215828483041417156157d75790509050610280516102e0518082028215828483041417156157d7579050905081818301106157d757808201905090506102c05181818301106157d7578082019050905061030052610160516102e0518082028215828483041417156157d757905090506103205261032051610300511061323d576103008051610320518082106157d75780820390509050815250613253565b610240516002808204905090506101c05261348a565b610300516101c0518080156157d757820490509050610340526102c051610340518080156157d7578204905090506103605261030051670de0b6b3a7640000610160518082028215828483041417156157d7579050905081818301106157d75780820190509050610340518080156157d75782049050905061036051670de0b6b3a76400008082028215828483041417156157d75790509050610260518080156157d75782049050905081818301106157d75780820190509050610380526103608051670de0b6b3a7640000610280518082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090508152506103605161038051106133875761038051610360518082106157d757808203905090506101c052613399565b610240516002808204905090506101c0525b60006103a052610240516101c051116133cb57610240516101c0518082106157d757808203905090506103a0526133e6565b6101c051610240518082106157d757808203905090506103a0525b610200516101c051655af3107a400080820490509050808210613409578161340b565b805b905090506103a051101561348a576101c051670de0b6b3a76400008082028215828483041417156157d75790509050610160518080156157d7578204905090506103c052662386f26fc0ffff6103c05111613467576000613477565b68056bc75e2d631000016103c051105b156157d75750506101c051815250613512565b8151600101808352811415612fa85750506010610220527f446964206e6f7420636f6e7665726765000000000000000000000000000000006102405261022050610220518061024001818260206001820306601f82010390500336823750506308c379a06101e0526020610200526102205160206001820306601f82010390506044016101fcfd5b565b60e051670de0b6b3a7640000808204905090506101005260e05161010051670de0b6b3a76400008082028215828483041417156157d757905090508082106157d7578082039050905061012052603b6101005111156135775760008152506137f1565b670de0b6b3a76400006101006101005110156157d7576101005160020a8080156157d75782049050905061014052610120516135b957610140518152506137f1565b670de0b6b3a7640000610160526706f05b59d3b2000061018052670de0b6b3a76400006101a05260006101c0526101e0600160ff818352015b6101e051670de0b6b3a76400008082028215828483041417156157d757905090506102005261020051670de0b6b3a76400008082106157d7578082039050905061022052610220516101205111613662576102208051610120518082106157d75780820390509050815250613686565b61012051610220518082106157d75780820390509050610220526101c051156101c0525b6101605161022051610180518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508082028215828483041417156157d75790509050610200518080156157d757820490509050610160526101c051613708576101a080516101605181818301106157d75780820190509050815250613723565b6101a08051610160518082106157d757808203905090508152505b6402540be400610160511015613769575050610140516101a0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508152506137f1565b81516001018083528114156135f257505060106101e0527f446964206e6f7420636f6e766572676500000000000000000000000000000000610200526101e0506101e0518061020001818260206001820306601f82010390500336823750506308c379a06101a05260206101c0526101e05160206001820306601f82010390506044016101bcfd5b565b6017546020604038036080396080518082028215828483041417156157d7579050905081526018546020604038036020016080396080518082028215828483041417156157d757905090506001548082028215828483041417156157d75790509050670de0b6b3a764000080820490509050816020015250565b60085460e052600654610100526fffffffffffffffffffffffffffffffff6101005116610120526101005160801c6101405260e0514210156139ce57600554610160526007546101805260e08051610180518082106157d7578082039050905081525042610180518082106157d757808203905090506101805260e051610180518082106157d757808203905090506101a0526101605160801c6101a0518082028215828483041417156157d7579050905061014051610180518082028215828483041417156157d7579050905081818301106157d7578082019050905060e0518080156157d757820490509050610140526fffffffffffffffffffffffffffffffff61016051166101a0518082028215828483041417156157d7579050905061012051610180518082028215828483041417156157d7579050905081818301106157d7578082019050905060e0518080156157d757820490509050610120525b61014051815261012051816020015250565b600b546101205260e0516101005181818301106157d757808201905090506101405261012051670de0b6b3a76400008082028215828483041417156157d7579050905061012051670de0b6b3a764000081818301106157d75780820190509050673782dace9d90000060e0518082028215828483041417156157d75790509050610140518080156157d757820490509050610100518082028215828483041417156157d75790509050610140518080156157d7578204905090508082106157d757808203905090508080156157d75782049050905061014052601154610140518082028215828483041417156157d75790509050601254670de0b6b3a7640000610140518082106157d757808203905090508082028215828483041417156157d7579050905081818301106157d75780820190509050670de0b6b3a764000080820490509050815250565b610200516002808204905090506102205261020051670de0b6b3a76400008082028215828483041417156157d7579050905060015460028082028215828483041417156157d757905090508080156157d757820490509050610240526102205160e0526102405161010052600161012052613ba761026061249b565b61026051815250565b613bbb6104e061386d565b6104e080516104a05280602001516104c05250601c546104e052601d54610500526080380360208160803960805161052052602081602001608039608051610540525061056060006002818352015b6105605115613c77576370a0823161058052306105a0526020610580602461059c6105206105605160028110156157d75760200201515afa613c51573d600060003e3d6000fd5b601f3d11156157d7576105805160016105605160028110156157d7570260170155613c8d565b4760016105605160028110156157d75702601701555b8151600101808352811415613c0a575050601e5461056052610500516104e0511115613e2c576104e051610500518082106157d757808203905090506013548082028215828483041417156157d757905090506404a817c80080820490509050610580526000610580511115613e2c576024546105a05260006105a05114613e2c5761056051670de0b6b3a76400008082028215828483041417156157d7579050905061056051610580518082106157d757808203905090508080156157d757820490509050670de0b6b3a76400008082106157d757808203905090506105c052636962f845610600526105a051610620526105c051610640526020610600604461061c6000602060a038036080396080515af1613db0573d600060003e3d6000fd5b601f3d11156157d757610600516105e0526104e080516105805160028082028215828483041417156157d757905090508082106157d757808203905090508152506104e051601c556105a0517f6059a38198b1dc42b3791087d1ff0fbd72b3179553c25f678cd246f52ffaaf596105e051610600526020610600a25b6318160ddd6105a05260206105a060046105bc602060a038036080396080515afa613e5c573d600060003e3d6000fd5b601f3d11156157d7576105a051610580526104a051610620526104c05161064052613e886105c06137f3565b6105c0805161066052806020015161068052506106205161020052610640516102205261066051610240526106805161026052613ec6610600612666565b610600516105a0526105a051601955670de0b6b3a76400006105a05161020052613ef16105c0613b2b565b6105c0518082028215828483041417156157d75790509050610580518080156157d757820490509050601e55610500516104e0511115613f33576104e051601d555b565b60025461076052600354610780526001546107a0526004546107c05260006107e052426107c051101561403f57600f5461080052426107c0518082106157d75780820390509050670de0b6b3a76400008082028215828483041417156157d75790509050610800518080156157d75782049050905060e052613fb8610840613514565b610840516108205261078051670de0b6b3a7640000610820518082106157d757808203905090508082028215828483041417156157d7579050905061076051610820518082028215828483041417156157d7579050905081818301106157d75780820190509050670de0b6b3a7640000808204905090506107605261076051600255426004555b610740516108005261074051614083576106a051610200526106c051610220526106e05161024052610700516102605261407a610820612666565b61082051610800525b6000610720511161414d576106e05161082052610700516108405261082051620f4240808204905090506108605261082080516108605181818301106157d757808201905090508152506107a051610860518082028215828483041417156157d75790509050610700516106a05160e0526106c05161010052610820516101205261084051610140526108005161016052600161018052614125610880612df5565b610880518082106157d757808203905090508080156157d75782049050905061078052614156565b61072051610780525b610780516003556318160ddd610840526020610840600461085c602060a038036080396080515afa61418d573d600060003e3d6000fd5b601f3d11156157d7576108405161082052601c5461084052601e5461086052610800516002808204905090506108805261080051670de0b6b3a76400008082028215828483041417156157d7579050905060026107a0518082028215828483041417156157d757905090508080156157d7578204905090506108a052670de0b6b3a76400006108c052670de0b6b3a76400006108e052600061086051111561436c576108805160e0526108a0516101005260016101205261424f61092061249b565b6109205161090052670de0b6b3a7640000610900518082028215828483041417156157d75790509050610820518080156157d7578204905090506108e052610840516108e0518082028215828483041417156157d75790509050610860518080156157d7578204905090506108c05260085461092052610860516108e051106142d95760006142df565b61092051155b1561435b576004610940527f4c6f7373000000000000000000000000000000000000000000000000000000006109605261094050610940518061096001818260206001820306601f82010390500336823750506308c379a0610900526020610920526109405160206001820306601f820103905060440161091cfd5b6001610920511861436c5760006008555b6108c051601c5561076051670de0b6b3a76400008082028215828483041417156157d757905090506107a0518080156157d75782049050905061090052670de0b6b3a764000061090051116143df57670de0b6b3a7640000610900518082106157d75780820390509050610900526143ff565b6109008051670de0b6b3a76400008082106157d757808203905090508152505b600d5461090051600a8082049050905080821061441c578161441e565b805b9050905061092052601f5461094052610940511561443d5760006144c3565b6108c05160026009548082028215828483041417156157d7579050905081818301106157d757808201905090506108e05160028082028215828483041417156157d75790509050670de0b6b3a76400008082106157d75780820390509050116144a75760006144c3565b6109205161090051116144bb5760006144c3565b600061086051115b156144d4576001610940526001601f555b610940511561471d576109205161090051116144f15760006144f9565b600061086051115b1561471d576107a05161090051610920518082106157d757808203905090508082028215828483041417156157d7579050905061092051610760518082028215828483041417156157d7579050905081818301106157d75780820190509050610900518080156157d7578204905090506107e0526106e05161088052610700516107e0518082028215828483041417156157d757905090506107a0518080156157d7578204905090506108a0526106a051610200526106c0516102205261088051610240526108a051610260526145d1610980612666565b6109805161096052610960516002808204905090506108805261096051670de0b6b3a76400008082028215828483041417156157d7579050905060026107e0518082028215828483041417156157d757905090508080156157d7578204905090506108a052670de0b6b3a76400006108805160e0526108a0516101005260016101205261465f61098061249b565b610980518082028215828483041417156157d75790509050610820518080156157d75782049050905061086052670de0b6b3a764000061086051116146a55760006146dc565b6108c0516002610860518082028215828483041417156157d75790509050670de0b6b3a76400008082106157d75780820390509050115b614703576000601f55610800516019556108e051601e55614741613bb0566147415661471d565b6107e0516001556109605160195561086051601e55614741565b610800516019556108e051601e556109405115614741576000601f55614741613bb0565b565b6020546157d757610a00516109e051146157d75760026109e05110156157d7576002610a005110156157d7576000610a205111156157d757614786610ac061386d565b610ac08051610a80528060200151610aa05250601754610ac052601854610ae052604036610b003760803803602081608039608051610b4052602081602001608039608051610b605250610a60516147df5760006147e5565b6109e051155b6148bc576109c0516157d7576323b872dd610b80526109a051610ba05230610bc052610a2051610be0526020610b806064610b9c6000610b406109e05160028110156157d75760200201515af1614841573d600060003e3d6000fd5b601f3d11156157d757610b8051156157d7576109e0516148ca57632e1a7d4d610b8052610a2051610ba052610b406109e05160028110156157d75760200201513b156157d757600060006024610b9c6000610b406109e05160028110156157d75760200201515af16148ca573d600060003e3d6000fd6148ca565b610a20516109c051186157d7575b610ac0610a005160028110156157d7576020020151610b8052610ac06109e05160028110156157d7576020020151610ba052610ba051610a205181818301106157d75780820190509050610ac06109e05160028110156157d7576020020152610ac06109e05160028110156157d757602002015160016109e05160028110156157d7570260170155600154610bc052610ac0516020604038036080396080518082028215828483041417156157d75790509050610ac052610ae051610bc0518082028215828483041417156157d757905090506020604038036020016080396080518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610ae052602060403803608039608051610be052602060403803602001608039608051610c005260016109e05118614a2657602060403803602001608039608051610be052602060403803608039608051610c00525b600854610c20526000610c20511115614b2357610ba08051610be0518082028215828483041417156157d7579050905081525060006109e0511115614a9657610ba051610bc0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610ba0525b610ac06109e05160028110156157d7576020020151610c4052610ba051610ac06109e05160028110156157d7576020020152610a805161020052610aa05161022052610ac05161024052610ae05161026052614af3610c60612666565b610c6051601955610c4051610ac06109e05160028110156157d7576020020152610c20514210614b235760016008555b610ac0610a005160028110156157d7576020020151610a805160e052610aa05161010052610ac05161012052610ae0516101405260195461016052610a005161018052614b71610c40612df5565b610c40518082106157d75780820390509050610b2052610ac0610a005160028110156157d757602002018051610b20518082106157d75780820390509050815250610b20805160018082106157d757808203905090508152506000610a00511115614c0d57610b2051670de0b6b3a76400008082028215828483041417156157d75790509050610bc0518080156157d757820490509050610b20525b610b208051610c00518080156157d757820490509050815250610b208051610ac05160e052610ae05161010052614c45610c406139e0565b610c4051610b20518082028215828483041417156157d757905090506402540be400808204905090508082106157d75780820390509050815250610a4051610b20511015614d04576008610c40527f536c697070616765000000000000000000000000000000000000000000000000610c6052610c4050610c405180610c6001818260206001820306601f82010390500336823750506308c379a0610c00526020610c2052610c405160206001820306601f8201039050604401610c1cfd5b610b808051610b20518082106157d75780820390509050815250610b80516001610a005160028110156157d7570260170155610a6051614d45576000614d4b565b610a0051155b614e1057610a0051614dae5763d0e30db0610c4052610b40610a005160028110156157d75760200201513b156157d757600060006004610c5c610b2051610b40610a005160028110156157d75760200201515af1614dae573d600060003e3d6000fd5b63a9059cbb610c40526109a051610c6052610b2051610c80526020610c406044610c5c6000610b40610a005160028110156157d75760200201515af1614df9573d600060003e3d6000fd5b601f3d11156157d757610c4051156157d757614e3e565b6000610c4052610c405060006000610c4051610c60610b20516109a0515af1614e3e573d600060003e3d6000fd5b610b808051610c00518082028215828483041417156157d757905090508152506000610a00511115614e9b57610b8051610bc0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610b80525b610b8051610ac0610a005160028110156157d7576020020152620186a0610a205111614ec8576000614ed2565b620186a0610b2051115b15614f9257610a2051610be0518082028215828483041417156157d75790509050610c4052610b2051610c00518082028215828483041417156157d75790509050610c60526109e05115614f5b57610c6051670de0b6b3a76400008082028215828483041417156157d75790509050610c40518080156157d757820490509050610b0052614f92565b610c4051670de0b6b3a76400008082028215828483041417156157d75790509050610c60518080156157d757820490509050610b00525b610a80516106a052610aa0516106c052610ac0516106e052610ae05161070052610b005161072052600061074052614fc8613f35565b6109a0517fb2e76ae99761dc136e598d4a629bb347eccb9532a5f8bbd72e18467c3c34cc986109e051610c4052610a2051610c6052610a0051610c8052610b2051610ca0526080610c40a2610b2051815250565b6101a05160e0526101c051610100526150366102006139e0565b6102005160028082028215828483041417156157d757905090506004808204905090506101e05260006102005261024060006002818352015b6020610240510261016001516102205261020080516102205181818301106157d75780820190509050815250815160010180835281141561506f575050610200516002808204905090506102205260006102405261028060006002818352015b6020610280510261016001516102605261022051610260511161511f57610240805161022051610260518082106157d7578082039050905081818301106157d7578082019050905081525061514e565b610240805161026051610220518082106157d7578082039050905081818301106157d757808201905090508152505b81516001018083528114156150cf5750506101e051610240518082028215828483041417156157d75790509050610200518080156157d757820490509050620186a081818301106157d75780820190509050815250565b6318160ddd610580526020610580600461059c602060a038036080396080515afa6151d5573d600060003e3d6000fd5b601f3d11156157d7576105805161056052610560516104e051116157d75760026105005110156157d757601754610580526018546105a05260006105c0526001546020604038036020016080396080518082028215828483041417156157d757905090506105e052610580516020604038036080396080518082028215828483041417156157d75790509050610600526105a0516105e0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061062052610500516152cb57670de0b6b3a76400006020604038036080396080518082028215828483041417156157d757905090506105e0525b610520516152df576019546105c052615313565b6104a051610200526104c051610220526106005161024052610620516102605261530a610640612666565b610640516105c0525b6105c051610640526106005160e05261062051610100526153356106806139e0565b61068051610660526104e051610640518082028215828483041417156157d75790509050610560518080156157d7578204905090506106805261064080516106805161066051610680518082028215828483041417156157d757905090506404a817c80080820490509050600181818301106157d757808201905090508082106157d757808203905090508082106157d757808203905090508152506104a05160e0526104c05161010052610600516101205261062051610140526106405161016052610500516101805261540b6106c0612df5565b6106c0516106a0526106006105005160028110156157d75760200201516106a0518082106157d75780820390509050670de0b6b3a76400008082028215828483041417156157d757905090506105e0518080156157d7578204905090506106c0526106a0516106006105005160028110156157d757602002015260006106e0526105405161549a5760006154b8565b620186a06106c051116154ae5760006154b8565b620186a06104e051115b1561565b57600061070052602060403803608039608051610720526001610500511861551e57610580516020604038036080396080518082028215828483041417156157d75790509050610700526020604038036020016080396080516107205261554a565b6105a0516020604038036020016080396080518082028215828483041417156157d75790509050610700525b61070051610680518082028215828483041417156157d757905090506105c0518080156157d7578204905090506107005261070051670de0b6b3a76400008082028215828483041417156157d757905090506106c051610720518082028215828483041417156157d75790509050610680516105806105005160028110156157d75760200201518082028215828483041417156157d75790509050610720518082028215828483041417156157d757905090506105c0518080156157d7578204905090508082106157d757808203905090508080156157d7578204905090506106e0526105005161565b576ec097ce7bc90715b34b9f10000000006106e0518080156157d7578204905090506106e0525b6106c05181526106e0516020820152610640516040820152606081016106005181526106205181602001525050565b60e05161569b5760008152506157d5565b60e051670de0b6b3a764000081818301106157d757808201905090506002808204905090506101005260e051610120526101406000610100818352015b6101205161010051186156f3575050610120518152506157d5565b610100516101205260e051670de0b6b3a76400008082028215828483041417156157d75790509050610100518080156157d7578204905090506101005181818301106157d757808201905090506002808204905090506101005281516001018083528114156156d85750506010610140527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101605261014050610140518061016001818260206001820306601f82010390500336823750506308c379a0610100526020610120526101405160206001820306601f820103905060440161011cfd5b565b600080fd5b6102ed615ac9036102ed6102c0396102ed615ac9036101a051816102c00152806102e0016101c05181526101e05181602001525080610320016102805181526102a0518160200152508060a0016102c0f35b600080fd000000000000000000000000babe61887f1de2713c6f97e567623453d3c79f67000000000000000000000000ecb456ea5365865ebab8a2661b0c503410e9b3470000000000000000000000000000000000000000000000000000000000061a80000000000000000000000000000000000000000000000000000083e0717e100000000000000000000000000000000000000000000000000000000000018cba800000000000000000000000000000000000000000000000000000000002aea540000000000000000000000000000000000000000000000000000001d1a94a20000000000000000000000000000000000000000000000000000000d12f0c4c6000000000000000000000000000000000000000000000000000000084c946232000000000000000000000000000000000000000000000000000000000012a05f2000000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000001716dc52ac88000000000000000000000000003a283d9c08e8b55966afb64c515f5143cf907611000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b

Deployed Bytecode

0x600436101561000d57612499565b60046000601c37600051635b41b908811861002d576000610cc052610048565b63394747c5811861008d576084358060011c6157d757610cc0525b6000546157d7576001600055336109a052346109c052608060046109e037610cc051610a6052610079610ce0614743565b610ce051610d00526020610d006000600055f35b6365b2489b81186100db576000546157d7576001600055336109a052346109c052608060046109e0376001610a60526100c7610cc0614743565b610cc051610ce0526020610ce06000600055f35b630b4c7e4d81186100f15760006109a05261010c565b63ee22be238118610a58576064358060011c6157d7576109a0525b6000546157d75760016000556020546157d75760006004351161013457600060243511610137565b60015b156157d757610147610a0061386d565b610a0080516109c05280602001516109e0525060803803602081608039608051610a0052602081602001608039608051610a205250601754610a4052601854610a605260e036610a8037610a4051610b6052610a6051610b8052610ba060006002818352015b610a40610ba05160028110156157d75760200201516020610ba051026004013581818301106157d75780820190509050610bc052610bc051610a40610ba05160028110156157d7576020020152610bc0516001610ba05160028110156157d757026017015581516001018083528114156101ad575050610a4051610ac052610a6051610ae0526001546020604038036020016080396080518082028215828483041417156157d75790509050610ba052610a40516020604038036080396080518082028215828483041417156157d75790509050610a4052610a6051610ba0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610a6052610b60516020604038036080396080518082028215828483041417156157d75790509050610b6052610b8051610ba0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610b80526109a05161031b57346157d7575b610bc060006002818352015b6109a05161033657600061033c565b610bc051155b15610353576020610bc051026004013534186157d7575b60006020610bc051026004013511156104a4576109a0511561037c576000610bc051141561037f565b60015b15610456576323b872dd610be05233610c005230610c20526020610bc0510260040135610c40526020610be06064610bfc6000610a00610bc05160028110156157d75760200201515af16103d8573d600060003e3d6000fd5b601f3d11156157d757610be051156157d757610bc05161045657632e1a7d4d610be0526020610bc0510260040135610c0052610a00610bc05160028110156157d75760200201513b156157d757600060006024610bfc6000610a00610bc05160028110156157d75760200201515af1610456573d600060003e3d6000fd5b610a40610bc05160028110156157d7576020020151610b60610bc05160028110156157d75760200201518082106157d75780820390509050610a80610bc05160028110156157d75760200201525b8151600101808352811415610327575050600854610bc0526000610bc051116104d357601954610b4052610516565b6109c051610200526109e05161022052610b605161024052610b8051610260526104fe610be0612666565b610be051610b4052610bc05142106105165760016008555b6109c051610200526109e05161022052610a405161024052610a605161026052610541610c00612666565b610c0051610be0526318160ddd610c20526020610c206004610c3c602060a038036080396080515afa610579573d600060003e3d6000fd5b601f3d11156157d757610c2051610c00526000610b4051116105b557610be051610200526105a8610c20613b2b565b610c2051610b00526105f9565b610c0051610be0518082028215828483041417156157d75790509050610b40518080156157d757820490509050610c00518082106157d75780820390509050610b00525b6000610b005111156157d7576000610b40511161068057610be051601955670de0b6b3a7640000601e55670de0b6b3a7640000601c556340c10f19610c205233610c4052610b0051610c60526020610c206044610c3c6000602060a038036080396080515af161066e573d600060003e3d6000fd5b601f3d11156157d757610c205061097a565b610a805161016052610aa05161018052610a40516101a052610a60516101c0526106ab610c2061501c565b610c2051610b00518082028215828483041417156157d757905090506402540be40080820490509050600181818301106157d75780820190509050610b2052610b008051610b20518082106157d75780820390509050815250610c008051610b005181818301106157d757808201905090508152506340c10f19610c205233610c4052610b0051610c60526020610c206044610c3c6000602060a038036080396080515af161075f573d600060003e3d6000fd5b601f3d11156157d757610c20506000610c2052620186a0610b0051111561094257600435156107915760243515610794565b60015b1561094257606036610c4037600435156107e857610ae0516020604038036020016080396080518082028215828483041417156157d75790509050610c4052602060403803608039608051610c605261082a565b610ac0516020604038036080396080518082028215828483041417156157d75790509050610c4052602060403803602001608039608051610c60526001610c80525b610c4051610b00518082028215828483041417156157d75790509050610c00518080156157d757820490509050610c4052610c4051670de0b6b3a76400008082028215828483041417156157d757905090506020610c80510260040135610c60518082028215828483041417156157d75790509050610b0051610ac0610c805160028110156157d75760200201518082028215828483041417156157d75790509050610c60518082028215828483041417156157d75790509050610c00518080156157d7578204905090508082106157d757808203905090508080156157d757820490509050610c2052610c8051610942576ec097ce7bc90715b34b9f1000000000610c20518080156157d757820490509050610c20525b6109c0516106a0526109e0516106c052610a40516106e052610a605161070052610c205161072052610be0516107405261097a613f35565b604435610b005110156109fe576008610c20527f536c697070616765000000000000000000000000000000000000000000000000610c4052610c2050610c205180610c4001818260206001820306601f82010390500336823750506308c379a0610be0526020610c0052610c205160206001820306601f8201039050604401610bfcfd5b337f540ab385f9b5d450a27404172caade516b3ba3f4be88239ac56a2ad1de2a1f5a600435610c2052602435610c4052610b2051610c6052610c0051610c80526080610c20a2610b0051610c20526020610c206000600055f35b63fc0c546a8118610a7d57346157d757602060a0380360803960805160e052602060e0f35b63c66106578118610acc57346157d7576080380360208160803960805160e052602081602001608039608051610100525060e060043560028110156157d7576020020151610120526020610120f35b63f446c1d08118610af657346157d757610ae76101c061386d565b6101c051610200526020610200f35b63b13739298118610b2357346157d757610b116101c061386d565b6101c060200151610200526020610200f35b63ddca3f438118610b7a57346157d757610b3e6101606137f3565b61016080516101c05280602001516101e052506101c05160e0526101e05161010052610b6b6101a06139e0565b6101a051610200526020610200f35b63bb7b8b808118610c1257346157d757670de0b6b3a764000060195461020052610ba5610280613b2b565b610280518082028215828483041417156157d757905090506318160ddd6102a05260206102a060046102bc602060a038036080396080515afa610bed573d600060003e3d6000fd5b601f3d11156157d7576102a0518080156157d7578204905090506102e05260206102e0f35b63556d6e9f8118610ef257346157d757602435600435146157d757600260043510156157d757600260243510156157d7576001546020604038036020016080396080518082028215828483041417156157d757905090506104a0526017546104c0526018546104e052610c8661054061386d565b610540805161050052806020015161052052506019546105405260006008541115610d0d57610500516105c052610520516105e052610cc66105606137f3565b610560805161060052806020015161062052506105c051610200526105e0516102205261060051610240526106205161026052610d046105a0612666565b6105a051610540525b6104c060043560028110156157d75760200201805160443581818301106157d757808201905090508152506104c0516020604038036080396080518082028215828483041417156157d757905090506104c0526104e0516104a0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090506104e0526105005160e05261052051610100526104c051610120526104e05161014052610540516101605260243561018052610dc9610580612df5565b61058051610560526104c060243560028110156157d7576020020151610560518082106157d7578082039050905060018082106157d7578082039050905061058052610560516104c060243560028110156157d7576020020152600060243511610e535761058080516020604038036080396080518080156157d757820490509050815250610e8a565b61058051670de0b6b3a76400008082028215828483041417156157d757905090506104a0518080156157d757820490509050610580525b61058080516104c05160e0526104e05161010052610ea96105a06139e0565b6105a051610580518082028215828483041417156157d757905090506402540be400808204905090508082106157d75780820390509050815250610580516105a05260206105a0f35b635b36389c8118610f0757600060e052610f21565b63269b5581811861126e576064358060011c6157d75760e0525b346157d7576000546157d7576001600055608038036020816080396080516101005260208160200160803960805161012052506318160ddd610160526020610160600461017c602060a038036080396080515afa610f84573d600060003e3d6000fd5b601f3d11156157d75761016051610140526379cc67906101605233610180526004356101a0526020610160604461017c6000602060a038036080396080515af1610fd3573d600060003e3d6000fd5b601f3d11156157d75761016050601754610160526018546101805260043560018082106157d757808203905090506101a0526101c060006002818352015b6101606101c05160028110156157d75760200201516101a0518082028215828483041417156157d75790509050610140518080156157d7578204905090506101e05260206101c05102602401356101e051106157d7576101606101c05160028110156157d75760200201516101e0518082106157d7578082039050905060016101c05160028110156157d75702601701556101e0516101606101c05160028110156157d757602002015260e0516110c95760006110cf565b6101c051155b611191576101c0516111325763d0e30db0610200526101006101c05160028110156157d75760200201513b156157d75760006000600461021c6101e0516101006101c05160028110156157d75760200201515af1611132573d600060003e3d6000fd5b63a9059cbb6102005233610220526101e051610240526020610200604461021c60006101006101c05160028110156157d75760200201515af161117a573d600060003e3d6000fd5b601f3d11156157d75761020051156157d7576111bc565b6000610200526102005060006000610200516102206101e051335af16111bc573d600060003e3d6000fd5b81516001018083528114156110115750506019546101c0526101c0516101c0516101a0518082028215828483041417156157d75790509050610140518080156157d7578204905090508082106157d75780820390509050601955337fdd3c0336a16f1b64f172b7bb0dad5b2b3c7c76f91e8c4aafd6aae60dce800153610160516101e0526101805161020052610140516004358082106157d757808203905090506102205260606101e0a26000600055005b638d8ea72781186114fa57346157d7576318160ddd6104c05260206104c060046104dc602060a038036080396080515afa6112ae573d600060003e3d6000fd5b601f3d11156157d7576104c0516104a0526001546020604038036020016080396080518082028215828483041417156157d757905090506104c0526112f461052061386d565b61052080516104e052806020015161050052506113126105606137f3565b610560805161052052806020015161054052506004356020604038036080396080518082028215828483041417156157d75790509050610560526024356104c0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610580526019546105a052600060085411156113c1576104e051610200526105005161022052610520516102405261054051610260526113b86105c0612666565b6105c0516105a0525b61052080516105605181818301106157d7578082019050905081525061054080516105805181818301106157d757808201905090508152506104e051610200526105005161022052610520516102405261054051610260526114246105e0612666565b6105e0516105c0526104a0516105c0518082028215828483041417156157d757905090506105a0518080156157d7578204905090506104a0518082106157d757808203905090506105e0526105e0805161056051610160526105805161018052610520516101a052610540516101c05261149f61060061501c565b610600516105e0518082028215828483041417156157d757905090506402540be40080820490509050600181818301106157d757808201905090508082106157d757808203905090508152506105e051610600526020610600f35b634fb08c5e811861158657346157d75761151561074061386d565b61074080516108205280602001516108405250604060046108603760016108a05260006108c052610820516104a052610840516104c052610860516104e05261088051610500526108a051610520526108c051610540526115776107806151a5565b610780516108e05260206108e0f35b63f1dc3cc9811861159c5760006109a0526115b7565b638f15b6b5811861190a576064358060011c6157d7576109a0525b346157d7576000546157d75760016000556020546157d7576115da610a0061386d565b610a0080516109c05280602001516109e0525060a036610a0037600854610aa0526109c0516104a0526109e0516104c052604060046104e0376000610aa051116105205260016105405261162f610ac06151a5565b610ac08051610a00526020810151610a40526040810151610a2052606081018051610a60528060200151610a80525050604435610a005110156116e3576008610ac0527f536c697070616765000000000000000000000000000000000000000000000000610ae052610ac050610ac05180610ae001818260206001820306601f82010390500336823750506308c379a0610a80526020610aa052610ac05160206001820306601f8201039050604401610a9cfd5b610aa05142106116f35760016008555b600160243560028110156157d757026017018054610a00518082106157d757808203905090508155506379cc6790610ac05233610ae052600435610b00526020610ac06044610adc6000602060a038036080396080515af161175a573d600060003e3d6000fd5b601f3d11156157d757610ac05060803803602081608039608051610ac052602081602001608039608051610ae052506109a05161179857600061179d565b602435155b61185b576024356117fd5763d0e30db0610b0052610ac060243560028110156157d75760200201513b156157d757600060006004610b1c610a0051610ac060243560028110156157d75760200201515af16117fd573d600060003e3d6000fd5b63a9059cbb610b005233610b2052610a0051610b40526020610b006044610b1c6000610ac060243560028110156157d75760200201515af1611844573d600060003e3d6000fd5b601f3d11156157d757610b0051156157d757611886565b6000610b0052610b005060006000610b0051610b20610a0051335af1611886573d600060003e3d6000fd5b6109c0516106a0526109e0516106c052610a60516106e052610a805161070052610a405161072052610a2051610740526118be613f35565b337f5ad056f2e28a8cec232015406b843668c1e36cda598127ec3b8c59b8c72773a060406004610b0037610a0051610b40526060610b00a2610a0051610b00526020610b006000600055f35b63c93f49e8811861193557346157d7576000546157d757600160005561192e613bb0565b6000600055005b635e2480728118611b3157346157d757601a5433186157d7576007546201517f81818301106157d757808201905090504211156157d757426201517f81818301106157d7578082019050905060443511156157d75761199561020061386d565b61020080516101c05280602001516101e052506101c05160801b610200526101e051610200511761020052610f9f60043511156157d75763ee6b280160043510156157d7576402540be3ff60243511156157d75766470de4df82000160243510156157d757670de0b6b3a76400006004358082028215828483041417156157d757905090506101c0518080156157d75782049050905061022052678ac7230489e800016102205110156157d75767016345785d89ffff6102205111156157d757670de0b6b3a76400006024358082028215828483041417156157d757905090506101e0518080156157d75782049050905061022052678ac7230489e800016102205110156157d75767016345785d89ffff6102205111156157d757610200516005554260075560043560801b61024052602435610240511761024052604435600855610240516006557fe35f0559b0642164e286b30df2077ec3a05426617a25db7578fd20ba39a6cd056101c05161026052600435610280526101e0516102a0526024356102c052426102e0526044356103005260c0610260a1005b63244c7c2e8118611bd457346157d757601a5433186157d757611b5561020061386d565b61020080516101c05280602001516101e052506101c05160801b610200526101e051610200511761020052610200516005556102005160065542600755426008557f5f0e7fba3d100c9e19446e1c92fe436f0a9a22fe99669360e4fdd6d3de2fc2846101c051610220526101e0516102405242610260526060610220a1005b63a43c33518118611d9a57346157d757601a5433186157d7576023546157d75760e0600460e0376402540be4016101005110611c165760125461010052611c25565b6207a11f6101005111156157d7575b6402540be40060e0511115611c3b5760115460e0525b6101005160e051116157d7576402540be400610120511115611c5f57601354610120525b670de0b6b3a76400006101405110611c7d57600b5461014052611c8a565b60006101405111156157d7575b670de0b6b3a7640000610160511115611ca557600954610160525b670de0b6b3a7640000610180511115611cc057600d54610180525b62093a806101a05110611cd957600f546101a052611ce6565b60006101a05111156157d7575b426203f48081818301106157d757808201905090506101c0526101c0516023556101205160165560e0516014556101005160155561014051600c5561016051600a5561018051600e556101a0516010556101c0517f913fde9a37e1f8ab67876a4d0ce80790d764fcfc5692f4529526df9c6bdde553610120516101e05260e0516102005261010051610220526101405161024052610160516102605261018051610280526101a0516102a05260e06101e0a2005b632a7dd7cd8118611eb457346157d7576000546157d7576001600055601a5433186157d75760235442106157d7576000602354146157d75760006023556016546106a0526106a05160135414611dfa57611df2613bb0565b6106a0516013555b6014546106c0526106c0516011556015546106e0526106e051601255600c546107005261070051600b55600a546107205261072051600955600e546107405261074051600d556010546107605261076051600f557f1c65bbdc939f346e5d6f0bde1f072819947438d4fc7b182cc59c2f6dc55040876106a051610780526106c0516107a0526106e0516107c052610700516107e05261072051610800526107405161082052610760516108405260e0610780a16000600055005b63226840fb8118611ed457346157d757601a5433186157d7576000602355005b636b441a408118611f58576004358060a01c6157d75760e052346157d757601a5433186157d7576022546157d757426203f48081818301106157d75780820190509050610100526101005160225560e051601b5560e051610100517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb9356000610120a3005b636a1c05ae8118611fc157346157d757601a5433186157d75760225442106157d7576000602254146157d7576000602255601b5460e05260e051601a5560e0517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c6000610100a2005b6386fbf1938118611fe157346157d757601a5433186157d7576000602255005b63e3698853811861200b57346157d757601a5433186157d7574260215411156157d7576001602055005b633046f972811861202b57346157d757601a5433186157d7576000602055005b637242e524811861205a576004358060a01c6157d75760e052346157d757601a5433186157d75760e051602455005b6354f0f7d581186120cf57346157d7576002601e548082028215828483041417156157d7579050905060025460e0526120946101a061568a565b6101a0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061018052610180516101a05260206101a0f35b63b9e8c9fd81186120eb57346157d75760015460e052602060e0f35b6386fc88d3811861210757346157d75760025460e052602060e0f35b63c146bf94811861212357346157d75760035460e052602060e0f35b636112c747811861213f57346157d75760045460e052602060e0f35b63204fe3d5811861215b57346157d75760055460e052602060e0f35b63f30cfad5811861217757346157d75760065460e052602060e0f35b63e89876ff811861219357346157d75760075460e052602060e0f35b63f9ed959781186121af57346157d75760085460e052602060e0f35b6349fe9e7781186121cb57346157d75760095460e052602060e0f35b63727ced5781186121e757346157d757600a5460e052602060e0f35b6372d4f0e2811861220357346157d757600b5460e052602060e0f35b63d7c3dcbe811861221f57346157d757600c5460e052602060e0f35b63083812e5811861223b57346157d757600d5460e052602060e0f35b634ea12c7d811861225757346157d757600e5460e052602060e0f35b63662b6274811861227357346157d757600f5460e052602060e0f35b630c5e23d4811861228f57346157d75760105460e052602060e0f35b6392526c0c81186122ab57346157d75760115460e052602060e0f35b63ee8de67581186122c757346157d75760125460e052602060e0f35b63fee3f7f981186122e357346157d75760135460e052602060e0f35b637cf9aedc81186122ff57346157d75760145460e052602060e0f35b637d1b060c811861231b57346157d75760155460e052602060e0f35b63e3824462811861233757346157d75760165460e052602060e0f35b634903b0d1811861236357346157d757600160043560028110156157d757026017015460e052602060e0f35b630f529ba2811861237f57346157d75760195460e052602060e0f35b638da5cb5b811861239b57346157d757601a5460e052602060e0f35b631ec0cdc181186123b757346157d757601b5460e052602060e0f35b637ba1a74d81186123d357346157d757601c5460e052602060e0f35b630b7b594b81186123ef57346157d757601d5460e052602060e0f35b630c46b72a811861240b57346157d757601e5460e052602060e0f35b639c868ac0811861242757346157d75760205460e052602060e0f35b632a426896811861244357346157d75760215460e052602060e0f35b63e0a0b586811861245f57346157d75760225460e052602060e0f35b63405e28f8811861247b57346157d75760235460e052602060e0f35b636e42e4d2811861249757346157d75760245460e052602060e0f35b505b005b60e051610140526101005161016052610120516124b95760006124c3565b6101605161014051105b156124d857610100516101405260e051610160525b610140516101805260006101a0526101c0600060ff818352015b610180516101e0526101805161014051610160518082028215828483041417156157d75790509050610180518080156157d75782049050905081818301106157d75780820190509050600280820490509050610180526101e0516101805111612574576101e051610180518082106157d757808203905090506101a05261258f565b610180516101e0518082106157d757808203905090506101a0525b60016101a05111156125c657610180516101a051670de0b6b3a76400008082028215828483041417156157d75790509050106125c9565b60015b156125dc57505061018051815250612664565b81516001018083528114156124f257505060106101c0527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101e0526101c0506101c051806101e001818260206001820306601f82010390500336823750506308c379a06101805260206101a0526101c05160206001820306601f820103905060440161019cfd5b565b610f9f6102005111612679576000612684565b63ee6b280161020051105b156157d7576402540be3ff610220511161269f5760006126ad565b66470de4df82000161022051105b156157d7576102405161028052610260516102a0526102a0516102805110156126e1576102605161028052610240516102a0525b633b9ac9ff61028051116126f657600061270b565b6d314dc6448d9338c15b0a0000000161028051105b156157d757655af3107a3fff6102a051670de0b6b3a76400008082028215828483041417156157d75790509050610280518080156157d75782049050905011156157d75760026102805160e0526102a051610100526000610120526127716102e061249b565b6102e0518082028215828483041417156157d757905090506102c052610280516102a05181818301106157d757808201905090506102e052610300600060ff818352015b6102c05161032052673782dace9d900000610280518082028215828483041417156157d757905090506102c0518080156157d7578204905090506102a0518082028215828483041417156157d757905090506102c0518080156157d7578204905090506103405261022051670de0b6b3a764000081818301106157d757808201905090506103605261034051610360511161287b5761034051610360518082106157d75780820390509050600181818301106157d75780820190509050610360526128a8565b61036051610340518082106157d75780820390509050600181818301106157d75780820190509050610360525b670de0b6b3a76400006102c0518082028215828483041417156157d75790509050610220518080156157d757820490509050610360518082028215828483041417156157d75790509050610220518080156157d757820490509050610360518082028215828483041417156157d757905090506127108082028215828483041417156157d75790509050610200518080156157d75782049050905061038052673782dace9d900000610340518082028215828483041417156157d75790509050610360518080156157d7578204905090506103a0526102e0516102e0516103a0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905081818301106157d757808201905090506103805160028082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090506103a0516102c0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508082106157d757808203905090506103c0526102c0516103c0516102e05181818301106157d757808201905090508082028215828483041417156157d757905090506103c0518080156157d7578204905090506103e0526102c0516102c0518082028215828483041417156157d757905090506103c0518080156157d7578204905090506104005261034051670de0b6b3a764000011612b565761040080516102c051610380516103c0518080156157d7578204905090508082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061034051670de0b6b3a76400008082106157d757808203905090508082028215828483041417156157d75790509050610340518080156157d7578204905090508082106157d75780820390509050815250612bec565b61040080516102c051610380516103c0518080156157d7578204905090508082028215828483041417156157d75790509050670de0b6b3a764000080820490509050670de0b6b3a7640000610340518082106157d757808203905090508082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090508152505b610400516103e05111612c2157610400516103e0518082106157d757808203905090506002808204905090506102c052612c3c565b6103e051610400518082106157d757808203905090506102c0525b600061042052610320516102c05111612c6e57610320516102c0518082106157d7578082039050905061042052612c89565b6102c051610320518082106157d75780820390509050610420525b662386f26fc100006102c051808210612ca25781612ca4565b805b9050905061042051655af3107a40008082028215828483041417156157d757905090501015612d6b5761046060006002818352015b6020610460510261028001516104405261044051670de0b6b3a76400008082028215828483041417156157d757905090506102c0518080156157d75782049050905061048052662386f26fc0ffff6104805111612d37576000612d47565b68056bc75e2d6310000161048051105b156157d7578151600101808352811415612cd957505050506102c051815250612df3565b81516001018083528114156127b55750506010610300527f446964206e6f7420636f6e7665726765000000000000000000000000000000006103205261030050610300518061032001818260206001820306601f82010390500336823750506308c379a06102c05260206102e0526103005160206001820306601f82010390506044016102dcfd5b565b610f9f60e05111612e07576000612e11565b63ee6b280160e051105b156157d7576402540be3ff6101005111612e2c576000612e3a565b66470de4df82000161010051105b156157d75767016345785d89ffff6101605111612e58576000612e6d565b6d314dc6448d9338c15b0a0000000161016051105b156157d7576101206001610180518082106157d7578082039050905060028110156157d75760200201516101a0527001000000000000000000000000000000006101605110156157d7576002610160510a6101a05160048082028215828483041417156157d757905090508080156157d7578204905090506101c052671bc16d674ec800006101a0518082028215828483041417156157d75790509050610160518080156157d7578204905090506101e05266470de4df81ffff6101e05111612f37576000612f47565b680ad78ebc5ac62000016101e051105b156157d7576101a051655af3107a40008082049050905061016051655af3107a400080820490509050808210612f7d5781612f7f565b805b905090506064808210612f925781612f94565b805b9050905061020052610220600060ff818352015b6101c051610240526101e0516101c0518082028215828483041417156157d7579050905060028082028215828483041417156157d75790509050610160518080156157d757820490509050610260526101a0516101c05181818301106157d757808201905090506102805261010051670de0b6b3a764000081818301106157d757808201905090506102a052610260516102a0511161307257610260516102a0518082106157d75780820390509050600181818301106157d757808201905090506102a05261309f565b6102a051610260518082106157d75780820390509050600181818301106157d757808201905090506102a0525b670de0b6b3a7640000610160518082028215828483041417156157d75790509050610100518080156157d7578204905090506102a0518082028215828483041417156157d75790509050610100518080156157d7578204905090506102a0518082028215828483041417156157d757905090506127108082028215828483041417156157d7579050905060e0518080156157d7578204905090506102c052670de0b6b3a7640000671bc16d674ec80000610260518082028215828483041417156157d757905090506102a0518080156157d75782049050905081818301106157d757808201905090506102e052670de0b6b3a76400006101c0518082028215828483041417156157d75790509050610280516102e0518082028215828483041417156157d7579050905081818301106157d757808201905090506102c05181818301106157d7578082019050905061030052610160516102e0518082028215828483041417156157d757905090506103205261032051610300511061323d576103008051610320518082106157d75780820390509050815250613253565b610240516002808204905090506101c05261348a565b610300516101c0518080156157d757820490509050610340526102c051610340518080156157d7578204905090506103605261030051670de0b6b3a7640000610160518082028215828483041417156157d7579050905081818301106157d75780820190509050610340518080156157d75782049050905061036051670de0b6b3a76400008082028215828483041417156157d75790509050610260518080156157d75782049050905081818301106157d75780820190509050610380526103608051670de0b6b3a7640000610280518082028215828483041417156157d75790509050610340518080156157d75782049050905081818301106157d757808201905090508152506103605161038051106133875761038051610360518082106157d757808203905090506101c052613399565b610240516002808204905090506101c0525b60006103a052610240516101c051116133cb57610240516101c0518082106157d757808203905090506103a0526133e6565b6101c051610240518082106157d757808203905090506103a0525b610200516101c051655af3107a400080820490509050808210613409578161340b565b805b905090506103a051101561348a576101c051670de0b6b3a76400008082028215828483041417156157d75790509050610160518080156157d7578204905090506103c052662386f26fc0ffff6103c05111613467576000613477565b68056bc75e2d631000016103c051105b156157d75750506101c051815250613512565b8151600101808352811415612fa85750506010610220527f446964206e6f7420636f6e7665726765000000000000000000000000000000006102405261022050610220518061024001818260206001820306601f82010390500336823750506308c379a06101e0526020610200526102205160206001820306601f82010390506044016101fcfd5b565b60e051670de0b6b3a7640000808204905090506101005260e05161010051670de0b6b3a76400008082028215828483041417156157d757905090508082106157d7578082039050905061012052603b6101005111156135775760008152506137f1565b670de0b6b3a76400006101006101005110156157d7576101005160020a8080156157d75782049050905061014052610120516135b957610140518152506137f1565b670de0b6b3a7640000610160526706f05b59d3b2000061018052670de0b6b3a76400006101a05260006101c0526101e0600160ff818352015b6101e051670de0b6b3a76400008082028215828483041417156157d757905090506102005261020051670de0b6b3a76400008082106157d7578082039050905061022052610220516101205111613662576102208051610120518082106157d75780820390509050815250613686565b61012051610220518082106157d75780820390509050610220526101c051156101c0525b6101605161022051610180518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508082028215828483041417156157d75790509050610200518080156157d757820490509050610160526101c051613708576101a080516101605181818301106157d75780820190509050815250613723565b6101a08051610160518082106157d757808203905090508152505b6402540be400610160511015613769575050610140516101a0518082028215828483041417156157d75790509050670de0b6b3a7640000808204905090508152506137f1565b81516001018083528114156135f257505060106101e0527f446964206e6f7420636f6e766572676500000000000000000000000000000000610200526101e0506101e0518061020001818260206001820306601f82010390500336823750506308c379a06101a05260206101c0526101e05160206001820306601f82010390506044016101bcfd5b565b6017546020604038036080396080518082028215828483041417156157d7579050905081526018546020604038036020016080396080518082028215828483041417156157d757905090506001548082028215828483041417156157d75790509050670de0b6b3a764000080820490509050816020015250565b60085460e052600654610100526fffffffffffffffffffffffffffffffff6101005116610120526101005160801c6101405260e0514210156139ce57600554610160526007546101805260e08051610180518082106157d7578082039050905081525042610180518082106157d757808203905090506101805260e051610180518082106157d757808203905090506101a0526101605160801c6101a0518082028215828483041417156157d7579050905061014051610180518082028215828483041417156157d7579050905081818301106157d7578082019050905060e0518080156157d757820490509050610140526fffffffffffffffffffffffffffffffff61016051166101a0518082028215828483041417156157d7579050905061012051610180518082028215828483041417156157d7579050905081818301106157d7578082019050905060e0518080156157d757820490509050610120525b61014051815261012051816020015250565b600b546101205260e0516101005181818301106157d757808201905090506101405261012051670de0b6b3a76400008082028215828483041417156157d7579050905061012051670de0b6b3a764000081818301106157d75780820190509050673782dace9d90000060e0518082028215828483041417156157d75790509050610140518080156157d757820490509050610100518082028215828483041417156157d75790509050610140518080156157d7578204905090508082106157d757808203905090508080156157d75782049050905061014052601154610140518082028215828483041417156157d75790509050601254670de0b6b3a7640000610140518082106157d757808203905090508082028215828483041417156157d7579050905081818301106157d75780820190509050670de0b6b3a764000080820490509050815250565b610200516002808204905090506102205261020051670de0b6b3a76400008082028215828483041417156157d7579050905060015460028082028215828483041417156157d757905090508080156157d757820490509050610240526102205160e0526102405161010052600161012052613ba761026061249b565b61026051815250565b613bbb6104e061386d565b6104e080516104a05280602001516104c05250601c546104e052601d54610500526080380360208160803960805161052052602081602001608039608051610540525061056060006002818352015b6105605115613c77576370a0823161058052306105a0526020610580602461059c6105206105605160028110156157d75760200201515afa613c51573d600060003e3d6000fd5b601f3d11156157d7576105805160016105605160028110156157d7570260170155613c8d565b4760016105605160028110156157d75702601701555b8151600101808352811415613c0a575050601e5461056052610500516104e0511115613e2c576104e051610500518082106157d757808203905090506013548082028215828483041417156157d757905090506404a817c80080820490509050610580526000610580511115613e2c576024546105a05260006105a05114613e2c5761056051670de0b6b3a76400008082028215828483041417156157d7579050905061056051610580518082106157d757808203905090508080156157d757820490509050670de0b6b3a76400008082106157d757808203905090506105c052636962f845610600526105a051610620526105c051610640526020610600604461061c6000602060a038036080396080515af1613db0573d600060003e3d6000fd5b601f3d11156157d757610600516105e0526104e080516105805160028082028215828483041417156157d757905090508082106157d757808203905090508152506104e051601c556105a0517f6059a38198b1dc42b3791087d1ff0fbd72b3179553c25f678cd246f52ffaaf596105e051610600526020610600a25b6318160ddd6105a05260206105a060046105bc602060a038036080396080515afa613e5c573d600060003e3d6000fd5b601f3d11156157d7576105a051610580526104a051610620526104c05161064052613e886105c06137f3565b6105c0805161066052806020015161068052506106205161020052610640516102205261066051610240526106805161026052613ec6610600612666565b610600516105a0526105a051601955670de0b6b3a76400006105a05161020052613ef16105c0613b2b565b6105c0518082028215828483041417156157d75790509050610580518080156157d757820490509050601e55610500516104e0511115613f33576104e051601d555b565b60025461076052600354610780526001546107a0526004546107c05260006107e052426107c051101561403f57600f5461080052426107c0518082106157d75780820390509050670de0b6b3a76400008082028215828483041417156157d75790509050610800518080156157d75782049050905060e052613fb8610840613514565b610840516108205261078051670de0b6b3a7640000610820518082106157d757808203905090508082028215828483041417156157d7579050905061076051610820518082028215828483041417156157d7579050905081818301106157d75780820190509050670de0b6b3a7640000808204905090506107605261076051600255426004555b610740516108005261074051614083576106a051610200526106c051610220526106e05161024052610700516102605261407a610820612666565b61082051610800525b6000610720511161414d576106e05161082052610700516108405261082051620f4240808204905090506108605261082080516108605181818301106157d757808201905090508152506107a051610860518082028215828483041417156157d75790509050610700516106a05160e0526106c05161010052610820516101205261084051610140526108005161016052600161018052614125610880612df5565b610880518082106157d757808203905090508080156157d75782049050905061078052614156565b61072051610780525b610780516003556318160ddd610840526020610840600461085c602060a038036080396080515afa61418d573d600060003e3d6000fd5b601f3d11156157d7576108405161082052601c5461084052601e5461086052610800516002808204905090506108805261080051670de0b6b3a76400008082028215828483041417156157d7579050905060026107a0518082028215828483041417156157d757905090508080156157d7578204905090506108a052670de0b6b3a76400006108c052670de0b6b3a76400006108e052600061086051111561436c576108805160e0526108a0516101005260016101205261424f61092061249b565b6109205161090052670de0b6b3a7640000610900518082028215828483041417156157d75790509050610820518080156157d7578204905090506108e052610840516108e0518082028215828483041417156157d75790509050610860518080156157d7578204905090506108c05260085461092052610860516108e051106142d95760006142df565b61092051155b1561435b576004610940527f4c6f7373000000000000000000000000000000000000000000000000000000006109605261094050610940518061096001818260206001820306601f82010390500336823750506308c379a0610900526020610920526109405160206001820306601f820103905060440161091cfd5b6001610920511861436c5760006008555b6108c051601c5561076051670de0b6b3a76400008082028215828483041417156157d757905090506107a0518080156157d75782049050905061090052670de0b6b3a764000061090051116143df57670de0b6b3a7640000610900518082106157d75780820390509050610900526143ff565b6109008051670de0b6b3a76400008082106157d757808203905090508152505b600d5461090051600a8082049050905080821061441c578161441e565b805b9050905061092052601f5461094052610940511561443d5760006144c3565b6108c05160026009548082028215828483041417156157d7579050905081818301106157d757808201905090506108e05160028082028215828483041417156157d75790509050670de0b6b3a76400008082106157d75780820390509050116144a75760006144c3565b6109205161090051116144bb5760006144c3565b600061086051115b156144d4576001610940526001601f555b610940511561471d576109205161090051116144f15760006144f9565b600061086051115b1561471d576107a05161090051610920518082106157d757808203905090508082028215828483041417156157d7579050905061092051610760518082028215828483041417156157d7579050905081818301106157d75780820190509050610900518080156157d7578204905090506107e0526106e05161088052610700516107e0518082028215828483041417156157d757905090506107a0518080156157d7578204905090506108a0526106a051610200526106c0516102205261088051610240526108a051610260526145d1610980612666565b6109805161096052610960516002808204905090506108805261096051670de0b6b3a76400008082028215828483041417156157d7579050905060026107e0518082028215828483041417156157d757905090508080156157d7578204905090506108a052670de0b6b3a76400006108805160e0526108a0516101005260016101205261465f61098061249b565b610980518082028215828483041417156157d75790509050610820518080156157d75782049050905061086052670de0b6b3a764000061086051116146a55760006146dc565b6108c0516002610860518082028215828483041417156157d75790509050670de0b6b3a76400008082106157d75780820390509050115b614703576000601f55610800516019556108e051601e55614741613bb0566147415661471d565b6107e0516001556109605160195561086051601e55614741565b610800516019556108e051601e556109405115614741576000601f55614741613bb0565b565b6020546157d757610a00516109e051146157d75760026109e05110156157d7576002610a005110156157d7576000610a205111156157d757614786610ac061386d565b610ac08051610a80528060200151610aa05250601754610ac052601854610ae052604036610b003760803803602081608039608051610b4052602081602001608039608051610b605250610a60516147df5760006147e5565b6109e051155b6148bc576109c0516157d7576323b872dd610b80526109a051610ba05230610bc052610a2051610be0526020610b806064610b9c6000610b406109e05160028110156157d75760200201515af1614841573d600060003e3d6000fd5b601f3d11156157d757610b8051156157d7576109e0516148ca57632e1a7d4d610b8052610a2051610ba052610b406109e05160028110156157d75760200201513b156157d757600060006024610b9c6000610b406109e05160028110156157d75760200201515af16148ca573d600060003e3d6000fd6148ca565b610a20516109c051186157d7575b610ac0610a005160028110156157d7576020020151610b8052610ac06109e05160028110156157d7576020020151610ba052610ba051610a205181818301106157d75780820190509050610ac06109e05160028110156157d7576020020152610ac06109e05160028110156157d757602002015160016109e05160028110156157d7570260170155600154610bc052610ac0516020604038036080396080518082028215828483041417156157d75790509050610ac052610ae051610bc0518082028215828483041417156157d757905090506020604038036020016080396080518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610ae052602060403803608039608051610be052602060403803602001608039608051610c005260016109e05118614a2657602060403803602001608039608051610be052602060403803608039608051610c00525b600854610c20526000610c20511115614b2357610ba08051610be0518082028215828483041417156157d7579050905081525060006109e0511115614a9657610ba051610bc0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610ba0525b610ac06109e05160028110156157d7576020020151610c4052610ba051610ac06109e05160028110156157d7576020020152610a805161020052610aa05161022052610ac05161024052610ae05161026052614af3610c60612666565b610c6051601955610c4051610ac06109e05160028110156157d7576020020152610c20514210614b235760016008555b610ac0610a005160028110156157d7576020020151610a805160e052610aa05161010052610ac05161012052610ae0516101405260195461016052610a005161018052614b71610c40612df5565b610c40518082106157d75780820390509050610b2052610ac0610a005160028110156157d757602002018051610b20518082106157d75780820390509050815250610b20805160018082106157d757808203905090508152506000610a00511115614c0d57610b2051670de0b6b3a76400008082028215828483041417156157d75790509050610bc0518080156157d757820490509050610b20525b610b208051610c00518080156157d757820490509050815250610b208051610ac05160e052610ae05161010052614c45610c406139e0565b610c4051610b20518082028215828483041417156157d757905090506402540be400808204905090508082106157d75780820390509050815250610a4051610b20511015614d04576008610c40527f536c697070616765000000000000000000000000000000000000000000000000610c6052610c4050610c405180610c6001818260206001820306601f82010390500336823750506308c379a0610c00526020610c2052610c405160206001820306601f8201039050604401610c1cfd5b610b808051610b20518082106157d75780820390509050815250610b80516001610a005160028110156157d7570260170155610a6051614d45576000614d4b565b610a0051155b614e1057610a0051614dae5763d0e30db0610c4052610b40610a005160028110156157d75760200201513b156157d757600060006004610c5c610b2051610b40610a005160028110156157d75760200201515af1614dae573d600060003e3d6000fd5b63a9059cbb610c40526109a051610c6052610b2051610c80526020610c406044610c5c6000610b40610a005160028110156157d75760200201515af1614df9573d600060003e3d6000fd5b601f3d11156157d757610c4051156157d757614e3e565b6000610c4052610c405060006000610c4051610c60610b20516109a0515af1614e3e573d600060003e3d6000fd5b610b808051610c00518082028215828483041417156157d757905090508152506000610a00511115614e9b57610b8051610bc0518082028215828483041417156157d75790509050670de0b6b3a764000080820490509050610b80525b610b8051610ac0610a005160028110156157d7576020020152620186a0610a205111614ec8576000614ed2565b620186a0610b2051115b15614f9257610a2051610be0518082028215828483041417156157d75790509050610c4052610b2051610c00518082028215828483041417156157d75790509050610c60526109e05115614f5b57610c6051670de0b6b3a76400008082028215828483041417156157d75790509050610c40518080156157d757820490509050610b0052614f92565b610c4051670de0b6b3a76400008082028215828483041417156157d75790509050610c60518080156157d757820490509050610b00525b610a80516106a052610aa0516106c052610ac0516106e052610ae05161070052610b005161072052600061074052614fc8613f35565b6109a0517fb2e76ae99761dc136e598d4a629bb347eccb9532a5f8bbd72e18467c3c34cc986109e051610c4052610a2051610c6052610a0051610c8052610b2051610ca0526080610c40a2610b2051815250565b6101a05160e0526101c051610100526150366102006139e0565b6102005160028082028215828483041417156157d757905090506004808204905090506101e05260006102005261024060006002818352015b6020610240510261016001516102205261020080516102205181818301106157d75780820190509050815250815160010180835281141561506f575050610200516002808204905090506102205260006102405261028060006002818352015b6020610280510261016001516102605261022051610260511161511f57610240805161022051610260518082106157d7578082039050905081818301106157d7578082019050905081525061514e565b610240805161026051610220518082106157d7578082039050905081818301106157d757808201905090508152505b81516001018083528114156150cf5750506101e051610240518082028215828483041417156157d75790509050610200518080156157d757820490509050620186a081818301106157d75780820190509050815250565b6318160ddd610580526020610580600461059c602060a038036080396080515afa6151d5573d600060003e3d6000fd5b601f3d11156157d7576105805161056052610560516104e051116157d75760026105005110156157d757601754610580526018546105a05260006105c0526001546020604038036020016080396080518082028215828483041417156157d757905090506105e052610580516020604038036080396080518082028215828483041417156157d75790509050610600526105a0516105e0518082028215828483041417156157d75790509050670de0b6b3a76400008082049050905061062052610500516152cb57670de0b6b3a76400006020604038036080396080518082028215828483041417156157d757905090506105e0525b610520516152df576019546105c052615313565b6104a051610200526104c051610220526106005161024052610620516102605261530a610640612666565b610640516105c0525b6105c051610640526106005160e05261062051610100526153356106806139e0565b61068051610660526104e051610640518082028215828483041417156157d75790509050610560518080156157d7578204905090506106805261064080516106805161066051610680518082028215828483041417156157d757905090506404a817c80080820490509050600181818301106157d757808201905090508082106157d757808203905090508082106157d757808203905090508152506104a05160e0526104c05161010052610600516101205261062051610140526106405161016052610500516101805261540b6106c0612df5565b6106c0516106a0526106006105005160028110156157d75760200201516106a0518082106157d75780820390509050670de0b6b3a76400008082028215828483041417156157d757905090506105e0518080156157d7578204905090506106c0526106a0516106006105005160028110156157d757602002015260006106e0526105405161549a5760006154b8565b620186a06106c051116154ae5760006154b8565b620186a06104e051115b1561565b57600061070052602060403803608039608051610720526001610500511861551e57610580516020604038036080396080518082028215828483041417156157d75790509050610700526020604038036020016080396080516107205261554a565b6105a0516020604038036020016080396080518082028215828483041417156157d75790509050610700525b61070051610680518082028215828483041417156157d757905090506105c0518080156157d7578204905090506107005261070051670de0b6b3a76400008082028215828483041417156157d757905090506106c051610720518082028215828483041417156157d75790509050610680516105806105005160028110156157d75760200201518082028215828483041417156157d75790509050610720518082028215828483041417156157d757905090506105c0518080156157d7578204905090508082106157d757808203905090508080156157d7578204905090506106e0526105005161565b576ec097ce7bc90715b34b9f10000000006106e0518080156157d7578204905090506106e0525b6106c05181526106e0516020820152610640516040820152606081016106005181526106205181602001525050565b60e05161569b5760008152506157d5565b60e051670de0b6b3a764000081818301106157d757808201905090506002808204905090506101005260e051610120526101406000610100818352015b6101205161010051186156f3575050610120518152506157d5565b610100516101205260e051670de0b6b3a76400008082028215828483041417156157d75790509050610100518080156157d7578204905090506101005181818301106157d757808201905090506002808204905090506101005281516001018083528114156156d85750506010610140527f446964206e6f7420636f6e7665726765000000000000000000000000000000006101605261014050610140518061016001818260206001820306601f82010390500336823750506308c379a0610100526020610120526101405160206001820306601f820103905060440161011cfd5b565b600080fd0000000000000000000000003a283d9c08e8b55966afb64c515f5143cf907611000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001

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

000000000000000000000000babe61887f1de2713c6f97e567623453d3c79f67000000000000000000000000ecb456ea5365865ebab8a2661b0c503410e9b3470000000000000000000000000000000000000000000000000000000000061a80000000000000000000000000000000000000000000000000000083e0717e100000000000000000000000000000000000000000000000000000000000018cba800000000000000000000000000000000000000000000000000000000002aea540000000000000000000000000000000000000000000000000000001d1a94a20000000000000000000000000000000000000000000000000000000d12f0c4c6000000000000000000000000000000000000000000000000000000084c946232000000000000000000000000000000000000000000000000000000000012a05f2000000000000000000000000000000000000000000000000000000000000000258000000000000000000000000000000000000000000000000001716dc52ac88000000000000000000000000003a283d9c08e8b55966afb64c515f5143cf907611000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b

-----Decoded View---------------
Arg [0] : owner (address): 0xbabe61887f1de2713c6f97e567623453d3C79f67
Arg [1] : admin_fee_receiver (address): 0xeCb456EA5365865EbAb8a2661B0c503410e9B347
Arg [2] : A (uint256): 400000
Arg [3] : gamma (uint256): 145000000000000
Arg [4] : mid_fee (uint256): 26000000
Arg [5] : out_fee (uint256): 45000000
Arg [6] : allowed_extra_profit (uint256): 2000000000000
Arg [7] : fee_gamma (uint256): 230000000000000
Arg [8] : adjustment_step (uint256): 146000000000000
Arg [9] : admin_fee (uint256): 5000000000
Arg [10] : ma_half_time (uint256): 600
Arg [11] : initial_price (uint256): 6499060000000000
Arg [12] : _token (address): 0x3A283D9c08E8b55966afb64C515f5143cf907611
Arg [13] : _coins (address[2]): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B

-----Encoded View---------------
15 Constructor Arguments found :
Arg [0] : 000000000000000000000000babe61887f1de2713c6f97e567623453d3c79f67
Arg [1] : 000000000000000000000000ecb456ea5365865ebab8a2661b0c503410e9b347
Arg [2] : 0000000000000000000000000000000000000000000000000000000000061a80
Arg [3] : 000000000000000000000000000000000000000000000000000083e0717e1000
Arg [4] : 00000000000000000000000000000000000000000000000000000000018cba80
Arg [5] : 0000000000000000000000000000000000000000000000000000000002aea540
Arg [6] : 000000000000000000000000000000000000000000000000000001d1a94a2000
Arg [7] : 0000000000000000000000000000000000000000000000000000d12f0c4c6000
Arg [8] : 000000000000000000000000000000000000000000000000000084c946232000
Arg [9] : 000000000000000000000000000000000000000000000000000000012a05f200
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000258
Arg [11] : 000000000000000000000000000000000000000000000000001716dc52ac8800
Arg [12] : 0000000000000000000000003a283d9c08e8b55966afb64c515f5143cf907611
Arg [13] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [14] : 0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
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  ]
[ 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.