POL Price: $0.706575 (-3.97%)
 

Overview

POL Balance

Polygon PoS Chain LogoPolygon PoS Chain LogoPolygon PoS Chain Logo0 POL

POL Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CurveTricryptoMathOptimized

Compiler Version
vyper:0.3.10

Optimization Enabled:
N/A

Other Settings:
None license

Contract Source Code (Vyper language format)

# pragma version 0.3.10
# pragma optimize gas
# pragma evm-version paris

# (c) Curve.Fi, 2020-2023
# AMM Math for 3-coin Curve Cryptoswap Pools
#
# Unless otherwise agreed on, only contracts owned by Curve DAO or
# Swiss Stake GmbH are allowed to call this contract.

"""
@title CurveTricryptoMathOptimized
@author Curve.Fi
@license Copyright (c) Curve.Fi, 2020-2023 - all rights reserved
@notice Curve AMM Math for 3 unpegged assets (e.g. ETH, BTC, USD).
"""

N_COINS: constant(uint256) = 3
A_MULTIPLIER: constant(uint256) = 10000

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

MIN_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER / 100
MAX_A: constant(uint256) = N_COINS**N_COINS * A_MULTIPLIER * 1000

version: public(constant(String[8])) = "v2.0.0"


# ------------------------ AMM math functions --------------------------------


@external
@view
def get_y(
    _ANN: uint256, _gamma: uint256, x: uint256[N_COINS], _D: uint256, i: uint256
) -> uint256[2]:
    """
    @notice Calculate x[i] given other balances x[0..N_COINS-1] and invariant D.
    @dev ANN = A * N**N.
    @param _ANN AMM.A() value.
    @param _gamma AMM.gamma() value.
    @param x Balances multiplied by prices and precisions of all coins.
    @param _D Invariant.
    @param i Index of coin to calculate y.
    """

    # 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

    frac: uint256 = 0
    for k in range(3):
        if k != i:
            frac = x[k] * 10**18 / _D
            assert frac > 10**16 - 1 and frac < 10**20 + 1, "Unsafe values x[i]"
            # if above conditions are met, x[k] > 0

    j: uint256 = 0
    k: uint256 = 0
    if i == 0:
        j = 1
        k = 2
    elif i == 1:
        j = 0
        k = 2
    elif i == 2:
        j = 0
        k = 1

    ANN: int256 = convert(_ANN, int256)
    gamma: int256 = convert(_gamma, int256)
    D: int256 = convert(_D, int256)
    x_j: int256 = convert(x[j], int256)
    x_k: int256 = convert(x[k], int256)
    gamma2: int256 = unsafe_mul(gamma, gamma)

    a: int256 = 10**36 / 27

    # 10**36/9 + 2*10**18*gamma/27 - D**2/x_j*gamma**2*ANN/27**2/convert(A_MULTIPLIER, int256)/x_k
    b: int256 = (
        unsafe_add(
            10**36 / 9,
            unsafe_div(unsafe_mul(2 * 10**18, gamma), 27)
        )
        - unsafe_div(
            unsafe_div(
                unsafe_div(
                    unsafe_mul(
                        unsafe_div(unsafe_mul(D, D), x_j),
                        gamma2
                    ) * ANN,
                    27**2
                ),
                convert(A_MULTIPLIER, int256)
            ),
            x_k,
        )
    )  # <------- The first two expressions can be unsafe, and unsafely added.

    # 10**36/9 + gamma*(gamma + 4*10**18)/27 + gamma**2*(x_j+x_k-D)/D*ANN/27/convert(A_MULTIPLIER, int256)
    c: int256 = (
        unsafe_add(
            10**36 / 9,
            unsafe_div(unsafe_mul(gamma, unsafe_add(gamma, 4 * 10**18)), 27)
        )
        + unsafe_div(
            unsafe_div(
                unsafe_mul(
                    unsafe_div(gamma2 * unsafe_sub(unsafe_add(x_j, x_k), D), D),
                    ANN
                ),
                27
            ),
            convert(A_MULTIPLIER, int256),
        )
    )  # <--------- Same as above with the first two expressions. In the third
    #   expression, x_j + x_k will not overflow since we know their range from
    #                                              previous assert statements.

    # (10**18 + gamma)**2/27
    d: int256 = unsafe_div(unsafe_add(10**18, gamma)**2, 27)

    # abs(3*a*c/b - b)
    d0: int256 = abs(unsafe_mul(3, a) * c / b - b)  # <------------ a is smol.

    divider: int256 = 0
    if d0 > 10**48:
        divider = 10**30
    elif d0 > 10**44:
        divider = 10**26
    elif d0 > 10**40:
        divider = 10**22
    elif d0 > 10**36:
        divider = 10**18
    elif d0 > 10**32:
        divider = 10**14
    elif d0 > 10**28:
        divider = 10**10
    elif d0 > 10**24:
        divider = 10**6
    elif d0 > 10**20:
        divider = 10**2
    else:
        divider = 1

    additional_prec: int256 = 0
    if abs(a) > abs(b):
        additional_prec = abs(unsafe_div(a, b))
        a = unsafe_div(unsafe_mul(a, additional_prec), divider)
        b = unsafe_div(b * additional_prec, divider)
        c = unsafe_div(c * additional_prec, divider)
        d = unsafe_div(d * additional_prec, divider)
    else:
        additional_prec = abs(unsafe_div(b, a))
        a = unsafe_div(a / additional_prec, divider)
        b = unsafe_div(unsafe_div(b, additional_prec), divider)
        c = unsafe_div(unsafe_div(c, additional_prec), divider)
        d = unsafe_div(unsafe_div(d, additional_prec), divider)

    # 3*a*c/b - b
    _3ac: int256 = unsafe_mul(3, a) * c
    delta0: int256 = unsafe_div(_3ac, b) - b

    # 9*a*c/b - 2*b - 27*a**2/b*d/b
    delta1: int256 = (
        unsafe_div(3 * _3ac, b)
        - unsafe_mul(2, b)
        - unsafe_div(unsafe_div(27 * a**2, b) * d, b)
    )

    # delta1**2 + 4*delta0**2/b*delta0
    sqrt_arg: int256 = (
        delta1**2 +
        unsafe_div(4 * delta0**2, b) * delta0
    )

    sqrt_val: int256 = 0
    if sqrt_arg > 0:
        sqrt_val = convert(isqrt(convert(sqrt_arg, uint256)), int256)
    else:
        return [self._newton_y(_ANN, _gamma, x, _D, i), 0]

    b_cbrt: int256 = 0
    if b >= 0:
        b_cbrt = convert(self._cbrt(convert(b, uint256)), int256)
    else:
        b_cbrt = -convert(self._cbrt(convert(-b, uint256)), int256)

    second_cbrt: int256 = 0
    if delta1 > 0:
        # convert(self._cbrt(convert((delta1 + sqrt_val), uint256)/2), int256)
        second_cbrt = convert(
            self._cbrt(unsafe_div(convert(delta1 + sqrt_val, uint256), 2)),
            int256
        )
    else:
        second_cbrt = -convert(
            self._cbrt(unsafe_div(convert(-(delta1 - sqrt_val), uint256), 2)),
            int256
        )

    # b_cbrt*b_cbrt/10**18*second_cbrt/10**18
    C1: int256 = unsafe_div(
        unsafe_div(b_cbrt * b_cbrt, 10**18) * second_cbrt,
        10**18
    )

    # (b + b*delta0/C1 - C1)/3
    root_K0: int256 = unsafe_div(b + b * delta0 / C1 - C1, 3)

    # D*D/27/x_k*D/x_j*root_K0/a
    root: int256 = unsafe_div(
        unsafe_div(
            unsafe_div(unsafe_div(D * D, 27), x_k) * D,
            x_j
        ) * root_K0,
        a
    )

    out: uint256[2] = [
        convert(root, uint256),
        convert(unsafe_div(10**18 * root_K0, a), uint256)
    ]

    frac = unsafe_div(out[0] * 10**18, _D)
    assert frac >= 10**16 - 1 and frac < 10**20 + 1,  "Unsafe value for y"
    # due to precision issues, get_y can be off by 2 wei or so wrt _newton_y

    return out


@internal
@view
def _newton_y(
    ANN: uint256, gamma: uint256, x: uint256[N_COINS], D: uint256, i: uint256
) -> uint256:

    # Calculate x[i] given A, gamma, xp and D using newton's method.
    # This is the original method; get_y replaces it, but defaults to
    # this version conditionally.

    # We can ignore safuty checks since they are already done in get_y

    frac: uint256 = 0
    for k in range(3):
        if k != i:
            frac = x[k] * 10**18 / D
            assert frac > 10**16 - 1 and frac < 10**20 + 1, "Unsafe values x[i]"

    y: uint256 = D / N_COINS
    K0_i: uint256 = 10**18
    S_i: uint256 = 0

    x_sorted: uint256[N_COINS] = x
    x_sorted[i] = 0
    x_sorted = self._sort(x_sorted)  # From high to low

    convergence_limit: uint256 = max(max(x_sorted[0] / 10**14, D / 10**14), 100)

    for j in range(2, N_COINS + 1):
        _x: uint256 = x_sorted[N_COINS - j]
        y = y * D / (_x * N_COINS)  # Small _x first
        S_i += _x

    for j in range(N_COINS - 1):
        K0_i = K0_i * x_sorted[j] * N_COINS / D  # Large _x first

    # initialise variables:
    diff: uint256 = 0
    y_prev: uint256 = 0
    K0: uint256 = 0
    S: uint256 = 0
    _g1k0: uint256 = 0
    mul1: uint256 = 0
    mul2: uint256 = 0
    yfprime: uint256 = 0
    _dyfprime: uint256 = 0
    fprime: uint256 = 0
    y_minus: uint256 = 0
    y_plus: uint256 = 0

    for j in range(255):
        y_prev = y

        K0 = K0_i * y * N_COINS / D
        S = S_i + y

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

        # mul1 = 10**18 * D / gamma * _g1k0 / gamma * _g1k0 * A_MULTIPLIER / ANN
        mul1 = 10**18 * D / gamma * _g1k0 / gamma * _g1k0 * A_MULTIPLIER / ANN

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

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

        fprime = yfprime / y

        # y -= f / f_prime;  y = (y * fprime - f) / fprime
        y_minus = mul1 / fprime
        y_plus = (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

        if y > y_prev:
            diff = y - y_prev
        else:
            diff = y_prev - y

        if diff < max(convergence_limit, y / 10**14):
            frac = y * 10**18 / D
            assert frac > 10**16 - 1 and frac < 10**20 + 1,  "Unsafe value for y"
            return y

    raise "Did not converge"


@external
@view
def newton_D(
    ANN: uint256,
    gamma: uint256,
    x_unsorted: uint256[N_COINS],
    K0_prev: uint256 = 0,
) -> uint256:
    """
    @notice Finding the invariant via newtons method using good initial guesses.
    @dev ANN is higher by the factor A_MULTIPLIER
    @dev ANN is already A * N**N
    @param ANN the A * N**N value
    @param gamma the gamma value
    @param x_unsorted the array of coin balances (not sorted)
    @param K0_prev apriori for newton's method derived from get_y_int. Defaults
           to zero (no apriori)
    """
    x: uint256[N_COINS] = self._sort(x_unsorted)
    assert x[0] < max_value(uint256) / 10**18 * N_COINS**N_COINS  # dev: out of limits
    assert x[0] > 0  # dev: empty pool

    # Safe to do unsafe add since we checked largest x's bounds previously
    S: uint256 = unsafe_add(unsafe_add(x[0], x[1]), x[2])
    D: uint256 = 0

    if K0_prev == 0:
        # Geometric mean of 3 numbers cannot be larger than the largest number
        # so the following is safe to do:
        D = unsafe_mul(N_COINS, self._geometric_mean(x))
    else:
        if S > 10**36:
            D = self._cbrt(
                unsafe_div(
                    unsafe_div(x[0] * x[1], 10**36) * x[2],
                    K0_prev
                ) * 27 * 10**12
            )
        elif S > 10**24:
            D = self._cbrt(
                unsafe_div(
                    unsafe_div(x[0] * x[1], 10**24) * x[2],
                    K0_prev
                ) * 27 * 10**6
            )
        else:
            D = self._cbrt(
                unsafe_div(
                    unsafe_div(x[0] * x[1], 10**18) * x[2],
                    K0_prev
                ) * 27
            )

        # D not zero here if K0_prev > 0, and we checked if x[0] is gt 0.

    # initialise variables:
    K0: uint256 = 0
    _g1k0: uint256 = 0
    mul1: uint256 = 0
    mul2: uint256 = 0
    neg_fprime: uint256 = 0
    D_plus: uint256 = 0
    D_minus: uint256 = 0
    D_prev: uint256 = 0

    diff: uint256 = 0
    frac: uint256 = 0

    for i in range(255):

        D_prev = D

        # K0 = 10**18 * x[0] * N_COINS / D * x[1] * N_COINS / D * x[2] * N_COINS / D
        K0 = unsafe_div(
            unsafe_mul(
                unsafe_mul(
                    unsafe_div(
                        unsafe_mul(
                            unsafe_mul(
                                unsafe_div(
                                    unsafe_mul(
                                        unsafe_mul(10**18, x[0]), N_COINS
                                    ),
                                    D,
                                ),
                                x[1],
                            ),
                            N_COINS,
                        ),
                        D,
                    ),
                    x[2],
                ),
                N_COINS,
            ),
            D,
        )  # <-------- We can convert the entire expression using unsafe math.
        #   since x_i is not too far from D, so overflow is not expected. Also
        #      D > 0, since we proved that already. unsafe_div is safe. K0 > 0
        #        since we can safely assume that D < 10**18 * x[0]. K0 is also
        #                            in the range of 10**18 (it's a property).

        _g1k0 = unsafe_add(gamma, 10**18)  # <--------- safe to do unsafe_add.

        if _g1k0 > K0:  #       The following operations can safely be unsafe.
            _g1k0 = unsafe_add(unsafe_sub(_g1k0, K0), 1)
        else:
            _g1k0 = unsafe_add(unsafe_sub(K0, _g1k0), 1)

        # D / (A * N**N) * _g1k0**2 / gamma**2
        # mul1 = 10**18 * D / gamma * _g1k0 / gamma * _g1k0 * A_MULTIPLIER / ANN
        mul1 = unsafe_div(
            unsafe_mul(
                unsafe_mul(
                    unsafe_div(
                        unsafe_mul(
                            unsafe_div(unsafe_mul(10**18, D), gamma), _g1k0
                        ),
                        gamma,
                    ),
                    _g1k0,
                ),
                A_MULTIPLIER,
            ),
            ANN,
        )  # <------ Since D > 0, gamma is small, _g1k0 is small, the rest are
        #        non-zero and small constants, and D has a cap in this method,
        #                    we can safely convert everything to unsafe maths.

        # 2*N*K0 / _g1k0
        # mul2 = (2 * 10**18) * N_COINS * K0 / _g1k0
        mul2 = unsafe_div(
            unsafe_mul(2 * 10**18 * N_COINS, K0), _g1k0
        )  # <--------------- K0 is approximately around D, which has a cap of
        #      10**15 * 10**18 + 1, since we get that in get_y which is called
        #    with newton_D. _g1k0 > 0, so the entire expression can be unsafe.

        # neg_fprime: uint256 = (S + S * mul2 / 10**18) + mul1 * N_COINS / K0 - mul2 * D / 10**18
        neg_fprime = unsafe_sub(
            unsafe_add(
                unsafe_add(S, unsafe_div(unsafe_mul(S, mul2), 10**18)),
                unsafe_div(unsafe_mul(mul1, N_COINS), K0),
            ),
            unsafe_div(unsafe_mul(mul2, D), 10**18),
        )  # <--- mul1 is a big number but not huge: safe to unsafely multiply
        # with N_coins. neg_fprime > 0 if this expression executes.
        # mul2 is in the range of 10**18, since K0 is in that range, S * mul2
        # is safe. The first three sums can be done using unsafe math safely
        # and since the final expression will be small since mul2 is small, we
        # can safely do the entire expression unsafely.

        # D -= f / fprime
        # D * (neg_fprime + S) / neg_fprime
        D_plus = unsafe_div(D * unsafe_add(neg_fprime, S), neg_fprime)

        # D*D / neg_fprime
        D_minus = unsafe_div(D * D, neg_fprime)

        # Since we know K0 > 0, and neg_fprime > 0, several unsafe operations
        # are possible in the following. Also, (10**18 - K0) is safe to mul.
        # So the only expressions we keep safe are (D_minus + ...) and (D * ...)
        if 10**18 > K0:
            # D_minus += D * (mul1 / neg_fprime) / 10**18 * (10**18 - K0) / K0
            D_minus += unsafe_div(
                unsafe_mul(
                    unsafe_div(D * unsafe_div(mul1, neg_fprime), 10**18),
                    unsafe_sub(10**18, K0),
                ),
                K0,
            )
        else:
            # D_minus -= D * (mul1 / neg_fprime) / 10**18 * (K0 - 10**18) / K0
            D_minus -= unsafe_div(
                unsafe_mul(
                    unsafe_div(D * unsafe_div(mul1, neg_fprime), 10**18),
                    unsafe_sub(K0, 10**18),
                ),
                K0,
            )

        if D_plus > D_minus:
            D = unsafe_sub(D_plus, D_minus)  # <--------- Safe since we check.
        else:
            D = unsafe_div(unsafe_sub(D_minus, D_plus), 2)

        if D > D_prev:
            diff = unsafe_sub(D, D_prev)
        else:
            diff = unsafe_sub(D_prev, D)

        # Could reduce precision for gas efficiency here:
        if unsafe_mul(diff, 10**14) < max(10**16, D):

            # Test that we are safe with the next get_y
            for _x in x:
                frac = unsafe_div(unsafe_mul(_x, 10**18), D)
                assert frac >= 10**16 - 1 and frac < 10**20 + 1, "Unsafe values x[i]"

            return D
    raise "Did not converge"


@external
@view
def get_p(
    _xp: uint256[N_COINS], _D: uint256, _A_gamma: uint256[N_COINS-1]
) -> uint256[N_COINS-1]:
    """
    @notice Calculates dx/dy.
    @dev Output needs to be multiplied with price_scale to get the actual value.
    @param _xp Balances of the pool.
    @param _D Current value of D.
    @param _A_gamma Amplification coefficient and gamma.
    """

    assert _D > 10**17 - 1 and _D < 10**15 * 10**18 + 1  # dev: unsafe D values

    # K0 = P * N**N / D**N.
    # K0 is dimensionless and has 10**36 precision:
    K0: uint256 = unsafe_div(
        unsafe_div(unsafe_div(27 * _xp[0] * _xp[1], _D) * _xp[2], _D) * 10**36,
        _D
    )

    # GK0 is in 10**36 precision and is dimensionless.
    # GK0 = (
    #     2 * _K0 * _K0 / 10**36 * _K0 / 10**36
    #     + (gamma + 10**18)**2
    #     - (_K0 * _K0 / 10**36 * (2 * gamma + 3 * 10**18) / 10**18)
    # )
    # GK0 is always positive. So the following should never revert:
    GK0: uint256 = (
        unsafe_div(unsafe_div(2 * K0 * K0, 10**36) * K0, 10**36)
        + pow_mod256(unsafe_add(_A_gamma[1], 10**18), 2)
        - unsafe_div(
            unsafe_div(pow_mod256(K0, 2), 10**36) * unsafe_add(unsafe_mul(2, _A_gamma[1]), 3 * 10**18),
            10**18
        )
    )

    # NNAG2 = N**N * A * gamma**2
    NNAG2: uint256 = unsafe_div(unsafe_mul(_A_gamma[0], pow_mod256(_A_gamma[1], 2)), A_MULTIPLIER)

    # denominator = (GK0 + NNAG2 * x / D * _K0 / 10**36)
    denominator: uint256 = (GK0 + unsafe_div(unsafe_div(NNAG2 * _xp[0], _D) * K0, 10**36) )

    # p_xy = x * (GK0 + NNAG2 * y / D * K0 / 10**36) / y * 10**18 / denominator
    # p_xz = x * (GK0 + NNAG2 * z / D * K0 / 10**36) / z * 10**18 / denominator
    # p is in 10**18 precision.
    return [
        unsafe_div(
            _xp[0] * ( GK0 + unsafe_div(unsafe_div(NNAG2 * _xp[1], _D) * K0, 10**36) ) / _xp[1] * 10**18,
            denominator
        ),
        unsafe_div(
            _xp[0] * ( GK0 + unsafe_div(unsafe_div(NNAG2 * _xp[2], _D) * K0, 10**36) ) / _xp[2] * 10**18,
            denominator
        ),
    ]


# --------------------------- Math Utils -------------------------------------


@external
@view
def cbrt(x: uint256) -> uint256:
    """
    @notice Calculate the cubic root of a number in 1e18 precision
    @dev Consumes around 1500 gas units
    @param x The number to calculate the cubic root of
    """
    return self._cbrt(x)


@external
@view
def geometric_mean(_x: uint256[3]) -> uint256:
    """
    @notice Calculate the geometric mean of a list of numbers in 1e18 precision.
    @param _x list of 3 numbers to sort
    """
    return self._geometric_mean(_x)


@external
@view
def reduction_coefficient(x: uint256[N_COINS], fee_gamma: uint256) -> uint256:
    """
    @notice Calculates the reduction coefficient for the given x and fee_gamma
    @dev This method is used for calculating fees.
    @param x The x values
    @param fee_gamma The fee gamma value
    """
    return self._reduction_coefficient(x, fee_gamma)


@external
@view
def wad_exp(_power: int256) -> uint256:
    """
    @notice Calculates the e**x with 1e18 precision
    @param _power The number to calculate the exponential of
    """
    return self._snekmate_wad_exp(_power)


@internal
@pure
def _reduction_coefficient(x: uint256[N_COINS], fee_gamma: uint256) -> uint256:

    # fee_gamma / (fee_gamma + (1 - K))
    # where
    # K = prod(x) / (sum(x) / N)**N
    # (all normalized to 1e18)

    S: uint256 = x[0] + x[1] + x[2]

    # Could be good to pre-sort x, but it is used only for dynamic fee
    K: uint256 = 10**18 * N_COINS * x[0] / S
    K = unsafe_div(K * N_COINS * x[1], S)  # <- unsafe div is safu.
    K = unsafe_div(K * N_COINS * x[2], S)

    if fee_gamma > 0:
        K = fee_gamma * 10**18 / (fee_gamma + 10**18 - K)

    return K


@internal
@pure
def _snekmate_wad_exp(x: int256) -> uint256:

    """
    @dev Calculates the natural exponential function of a signed integer with
         a precision of 1e18.
    @notice Note that this function consumes about 810 gas units. The implementation
            is inspired by Remco Bloemen's implementation under the MIT license here:
            https://xn--2-umb.com/22/exp-ln.
    @dev This implementation is derived from Snekmate, which is authored
         by pcaversaccio (Snekmate), distributed under the AGPL-3.0 license.
         https://github.com/pcaversaccio/snekmate
    @param x The 32-byte variable.
    @return int256 The 32-byte calculation result.
    """
    value: int256 = x

    # If the result is `< 0.5`, we return zero. This happens when we have the following:
    # "x <= floor(log(0.5e18) * 1e18) ~ -42e18".
    if (x <= -42139678854452767551):
        return empty(uint256)

    # When the result is "> (2 ** 255 - 1) / 1e18" we cannot represent it as a signed integer.
    # This happens when "x >= floor(log((2 ** 255 - 1) / 1e18) * 1e18) ~ 135".
    assert x < 135305999368893231589, "wad_exp overflow"

    # `x` is now in the range "(-42, 136) * 1e18". Convert to "(-42, 136) * 2 ** 96" for higher
    # intermediate precision and a binary base. This base conversion is a multiplication with
    # "1e18 / 2 ** 96 = 5 ** 18 / 2 ** 78".
    value = unsafe_div(x << 78, 5 ** 18)

    # Reduce the range of `x` to "(-½ ln 2, ½ ln 2) * 2 ** 96" by factoring out powers of two
    # so that "exp(x) = exp(x') * 2 ** k", where `k` is a signer integer. Solving this gives
    # "k = round(x / log(2))" and "x' = x - k * log(2)". Thus, `k` is in the range "[-61, 195]".
    k: int256 = unsafe_add(unsafe_div(value << 96, 54916777467707473351141471128), 2 ** 95) >> 96
    value = unsafe_sub(value, unsafe_mul(k, 54916777467707473351141471128))

    # Evaluate using a "(6, 7)"-term rational approximation. Since `p` is monic,
    # we will multiply by a scaling factor later.
    y: int256 = unsafe_add(unsafe_mul(unsafe_add(value, 1346386616545796478920950773328), value) >> 96, 57155421227552351082224309758442)
    p: int256 = unsafe_add(unsafe_mul(unsafe_add(unsafe_mul(unsafe_sub(unsafe_add(y, value), 94201549194550492254356042504812), y) >> 96,\
                           28719021644029726153956944680412240), value), 4385272521454847904659076985693276 << 96)

    # We leave `p` in the "2 ** 192" base so that we do not have to scale it up
    # again for the division.
    q: int256 = unsafe_add(unsafe_mul(unsafe_sub(value, 2855989394907223263936484059900), value) >> 96, 50020603652535783019961831881945)
    q = unsafe_sub(unsafe_mul(q, value) >> 96, 533845033583426703283633433725380)
    q = unsafe_add(unsafe_mul(q, value) >> 96, 3604857256930695427073651918091429)
    q = unsafe_sub(unsafe_mul(q, value) >> 96, 14423608567350463180887372962807573)
    q = unsafe_add(unsafe_mul(q, value) >> 96, 26449188498355588339934803723976023)

    # The polynomial `q` has no zeros in the range because all its roots are complex.
    # No scaling is required, as `p` is already "2 ** 96" too large. Also,
    # `r` is in the range "(0.09, 0.25) * 2**96" after the division.
    r: int256 = unsafe_div(p, q)

    # To finalise the calculation, we have to multiply `r` by:
    #   - the scale factor "s = ~6.031367120",
    #   - the factor "2 ** k" from the range reduction, and
    #   - the factor "1e18 / 2 ** 96" for the base conversion.
    # We do this all at once, with an intermediate result in "2**213" base,
    # so that the final right shift always gives a positive value.

    # Note that to circumvent Vyper's safecast feature for the potentially
    # negative parameter value `r`, we first convert `r` to `bytes32` and
    # subsequently to `uint256`. Remember that the EVM default behaviour is
    # to use two's complement representation to handle signed integers.
    return unsafe_mul(convert(convert(r, bytes32), uint256), 3822833074963236453042738258902158003155416615667) >> convert(unsafe_sub(195, k), uint256)


@internal
@pure
def _snekmate_log_2(x: uint256, roundup: bool) -> uint256:
    """
    @notice An `internal` helper function that returns the log in base 2
         of `x`, following the selected rounding direction.
    @dev This implementation is derived from Snekmate, which is authored
         by pcaversaccio (Snekmate), distributed under the AGPL-3.0 license.
         https://github.com/pcaversaccio/snekmate
    @dev Note that it returns 0 if given 0. The implementation is
         inspired by OpenZeppelin's implementation here:
         https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/Math.sol.
    @param x The 32-byte variable.
    @param roundup The Boolean variable that specifies whether
           to round up or not. The default `False` is round down.
    @return uint256 The 32-byte calculation result.
    """
    value: uint256 = x
    result: uint256 = empty(uint256)

    # The following lines cannot overflow because we have the well-known
    # decay behaviour of `log_2(max_value(uint256)) < max_value(uint256)`.
    if x >> 128 != empty(uint256):
        value = x >> 128
        result = 128
    if value >> 64 != empty(uint256):
        value = value >> 64
        result = unsafe_add(result, 64)
    if value >> 32 != empty(uint256):
        value = value >> 32
        result = unsafe_add(result, 32)
    if value >> 16 != empty(uint256):
        value = value >> 16
        result = unsafe_add(result, 16)
    if value >> 8 != empty(uint256):
        value = value >> 8
        result = unsafe_add(result, 8)
    if value >> 4 != empty(uint256):
        value = value >> 4
        result = unsafe_add(result, 4)
    if value >> 2 != empty(uint256):
        value = value >> 2
        result = unsafe_add(result, 2)
    if value >> 1 != empty(uint256):
        result = unsafe_add(result, 1)

    if (roundup and (1 << result) < x):
        result = unsafe_add(result, 1)

    return result


@internal
@pure
def _cbrt(x: uint256) -> uint256:

    xx: uint256 = 0
    if x >= 115792089237316195423570985008687907853269 * 10**18:
        xx = x
    elif x >= 115792089237316195423570985008687907853269:
        xx = unsafe_mul(x, 10**18)
    else:
        xx = unsafe_mul(x, 10**36)

    log2x: int256 = convert(self._snekmate_log_2(xx, False), int256)

    # When we divide log2x by 3, the remainder is (log2x % 3).
    # So if we just multiply 2**(log2x/3) and discard the remainder to calculate our
    # guess, the newton method will need more iterations to converge to a solution,
    # since it is missing that precision. It's a few more calculations now to do less
    # calculations later:
    # pow = log2(x) // 3
    # remainder = log2(x) % 3
    # initial_guess = 2 ** pow * cbrt(2) ** remainder
    # substituting -> 2 = 1.26 ≈ 1260 / 1000, we get:
    #
    # initial_guess = 2 ** pow * 1260 ** remainder // 1000 ** remainder

    remainder: uint256 = convert(log2x, uint256) % 3
    a: uint256 = unsafe_div(
        unsafe_mul(
            pow_mod256(2, unsafe_div(convert(log2x, uint256), 3)),  # <- pow
            pow_mod256(1260, remainder),
        ),
        pow_mod256(1000, remainder),
    )

    # Because we chose good initial values for cube roots, 7 newton raphson iterations
    # are just about sufficient. 6 iterations would result in non-convergences, and 8
    # would be one too many iterations. Without initial values, the iteration count
    # can go up to 20 or greater. The iterations are unrolled. This reduces gas costs
    # but takes up more bytecode:
    a = unsafe_div(unsafe_add(unsafe_mul(2, a), unsafe_div(xx, unsafe_mul(a, a))), 3)
    a = unsafe_div(unsafe_add(unsafe_mul(2, a), unsafe_div(xx, unsafe_mul(a, a))), 3)
    a = unsafe_div(unsafe_add(unsafe_mul(2, a), unsafe_div(xx, unsafe_mul(a, a))), 3)
    a = unsafe_div(unsafe_add(unsafe_mul(2, a), unsafe_div(xx, unsafe_mul(a, a))), 3)
    a = unsafe_div(unsafe_add(unsafe_mul(2, a), unsafe_div(xx, unsafe_mul(a, a))), 3)
    a = unsafe_div(unsafe_add(unsafe_mul(2, a), unsafe_div(xx, unsafe_mul(a, a))), 3)
    a = unsafe_div(unsafe_add(unsafe_mul(2, a), unsafe_div(xx, unsafe_mul(a, a))), 3)

    if x >= 115792089237316195423570985008687907853269 * 10**18:
        a = unsafe_mul(a, 10**12)
    elif x >= 115792089237316195423570985008687907853269:
        a = unsafe_mul(a, 10**6)

    return a


@internal
@pure
def _sort(unsorted_x: uint256[3]) -> uint256[3]:

    # Sorts a three-array number in a descending order:

    x: uint256[N_COINS] = unsorted_x
    temp_var: uint256 = x[0]
    if x[0] < x[1]:
        x[0] = x[1]
        x[1] = temp_var
    if x[0] < x[2]:
        temp_var = x[0]
        x[0] = x[2]
        x[2] = temp_var
    if x[1] < x[2]:
        temp_var = x[1]
        x[1] = x[2]
        x[2] = temp_var

    return x


@internal
@view
def _geometric_mean(_x: uint256[3]) -> uint256:

    # calculates a geometric mean for three numbers.

    prod: uint256 = unsafe_div(
        unsafe_div(_x[0] * _x[1], 10**18) * _x[2],
        10**18
    )

    if prod == 0:
        return 0

    return self._cbrt(prod)

Contract Security Audit

Contract ABI

[{"stateMutability":"view","type":"function","name":"get_y","inputs":[{"name":"_ANN","type":"uint256"},{"name":"_gamma","type":"uint256"},{"name":"x","type":"uint256[3]"},{"name":"_D","type":"uint256"},{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256[2]"}]},{"stateMutability":"view","type":"function","name":"newton_D","inputs":[{"name":"ANN","type":"uint256"},{"name":"gamma","type":"uint256"},{"name":"x_unsorted","type":"uint256[3]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"newton_D","inputs":[{"name":"ANN","type":"uint256"},{"name":"gamma","type":"uint256"},{"name":"x_unsorted","type":"uint256[3]"},{"name":"K0_prev","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_p","inputs":[{"name":"_xp","type":"uint256[3]"},{"name":"_D","type":"uint256"},{"name":"_A_gamma","type":"uint256[2]"}],"outputs":[{"name":"","type":"uint256[2]"}]},{"stateMutability":"view","type":"function","name":"cbrt","inputs":[{"name":"x","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"geometric_mean","inputs":[{"name":"_x","type":"uint256[3]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"reduction_coefficient","inputs":[{"name":"x","type":"uint256[3]"},{"name":"fee_gamma","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"wad_exp","inputs":[{"name":"_power","type":"int256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"version","inputs":[],"outputs":[{"name":"","type":"string"}]}]

612b3e61001161000039612b3e610000f360003560e01c60026007821660011b612b2e01601e39600051565b6354fd4d5081186100995734612b295760208060805260066040527f76322e302e30000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f82600003163682375050601f19601f8251602001011690509050810190506080f35b63c7fab7088118611aee5760a436103417612b29576000610200526110ab56611aee565b634a2ab3be811861105b5760e436103417612b2957610a8c60043510156100e55760006100f0565b631017df8060043511155b15612b29576402540be400602435101561010b576000610119565b66b1a2bc2ec5000060243511155b15612b295767016345785d8a000060a435101561013757600061014c565b6d314dc6448d9338c15b0a0000000060a43511155b15612b295760006104e05260006003905b806105005260c4356105005114610247576105005160028111612b295760051b60440135670de0b6b3a7640000810281670de0b6b3a7640000820418612b2957905060a4358015612b2957808204905090506104e052662386f26fc100006104e05110156101cc5760006101dd565b68056bc75e2d631000006104e05111155b610247576012610520527f556e736166652076616c75657320785b695d00000000000000000000000000006105405261052050610520518061054001601f826000031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b60010181811861015d5750506040366105003760c435610272576001610500526002610520526102a4565b600160c4351861028d576000610500526002610520526102a4565b600260c435186102a4576000610500526001610520525b6004358060ff1c612b2957610540526024358060ff1c612b29576105605260a4358060ff1c612b2957610580526105005160028111612b295760051b604401358060ff1c612b29576105a0526105205160028111612b295760051b604401358060ff1c612b29576105c0526105605161056051026105e0526e0722112107720a4902cd0097b425ed61060052601b61056051671bc16d674ec8000002056e1566336316561edb086701c71c71c7016105c0516127106102d96105e0516105a05161058051610580510205026105405180820281191515600160ff1b8414151782158484840514171615612b2957905090500505058082038281136000831218612b29579050905061062052601b673782dace9d90000061056051016105605102056e1566336316561edb086701c71c71c701612710601b61054051610580516105e051610580516105c0516105a051010380820281191515600160ff1b8414151782158484840514171615612b295790509050050205058082018281126000831218612b29579050905061064052601b61056051670de0b6b3a7640000016fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a90500561066052610600516003026106405180820281191515600160ff1b8414151782158484840514171615612b295790509050610620518015612b2957808205600160ff1b8314156000198314151715612b295790509050610620518082038281136000831218612b2957905090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811315610520578061052f565b806000038114612b2957806000035b90506106805260006106a05273af298d050e4395d69670b12b7f410000000000016106805112156106845772047bf19673df52e37f2410011d10000000000161068051121561066f57701d6329f1c35ca4bfabb9f561000000000161068051121561065b576ec097ce7bc90715b34b9f1000000001610680511215610649576d04ee2d6d415b85acef8100000001610680511215610639576b204fce5e3e2502611000000161068051121561062a5769d3c21bcecceda100000161068051121561061d5768056bc75e2d631000016106805112156106125760016106a052610697565b60646106a052610697565b620f42406106a052610697565b6402540be4006106a052610697565b655af3107a40006106a052610697565b670de0b6b3a76400006106a052610697565b69021e19e0c9bab24000006106a052610697565b6a52b7d2dcc80cd2e40000006106a052610697565b6c0c9f2c9cd04674edea400000006106a0525b60006106c052610620517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156106cf57806106de565b806000038114612b2957806000035b9050610600517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156107125780610721565b806000038114612b2957806000035b9050136107e1576106005161062051057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81131561075f578061076e565b806000038114612b2957806000035b90506106c0526106a051610600516106c0518015612b2957808205600160ff1b8314156000198314151715612b29579050905005610600526106a0516106c051610620510505610620526106a0516106c051610640510505610640526106a0516106c051610660510505610660526108d9565b6106205161060051057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156108185780610827565b806000038114612b2957806000035b90506106c0526106a0516106c051610600510205610600526106a051610620516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610620526106a051610640516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610640526106a051610660516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610660525b610600516003026106405180820281191515600160ff1b8414151782158484840514171615612b2957905090506106e052610620516106e05105610620518082038281136000831218612b29579050905061070052610620516106e05160038102816003820518612b29579050056106205160011b8082038281136000831218612b2957905090506106205161062051610600516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a9050601b810281601b820518612b29579050056106605180820281191515600160ff1b8414151782158484840514171615612b295790509050058082038281136000831218612b29579050905061072052610720516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a905061062051610700516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a90508060021b816004820518612b29579050056107005180820281191515600160ff1b8414151782158484840514171615612b2957905090508082018281126000831218612b295790509050610740526000610760526001610740511215610b2d5760406004610120376060604461016037604060a46101c037610b11610780611b81565b610780516107a05260006107c05260406107a061105956610c26565b6107405160008112612b29578060b5710100000000000000000000000000000000008210610b62578160801c91508060401b90505b69010000000000000000008210610b80578160401c91508060201b90505b650100000000008210610b9a578160201c91508060101b90505b63010000008210610bb2578160101c91508060081b90505b620100008201810260121c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c905080830480828118828410021890509050905090508060ff1c612b2957610760525b6000610780526000610620511215610cbb57610620517f80000000000000000000000000000000000000000000000000000000000000008114612b295760000360008112612b295760c052610c7c6107a0612525565b6107a0518060ff1c612b29577f80000000000000000000000000000000000000000000000000000000000000008114612b295760000361078052610ce6565b6106205160008112612b295760c052610cd56107a0612525565b6107a0518060ff1c612b2957610780525b60006107a0526001610720511215610d955761072051610760518082038281136000831218612b2957905090507f80000000000000000000000000000000000000000000000000000000000000008114612b295760000360008112612b295760011c60c052610d566107c0612525565b6107c0518060ff1c612b29577f80000000000000000000000000000000000000000000000000000000000000008114612b29576000036107a052610dda565b61072051610760518082018281126000831218612b29579050905060008112612b295760011c60c052610dc96107c0612525565b6107c0518060ff1c612b29576107a0525b670de0b6b3a7640000670de0b6b3a7640000610780516107805180820281191515600160ff1b8414151782158484840514171615612b295790509050056107a05180820281191515600160ff1b8414151782158484840514171615612b295790509050056107c052600361062051610620516107005180820281191515600160ff1b8414151782158484840514171615612b2957905090506107c0518015612b2957808205600160ff1b8314156000198314151715612b2957905090508082018281126000831218612b2957905090506107c0518082038281136000831218612b295790509050056107e052610600516105a0516105c051601b610580516105805180820281191515600160ff1b8414151782158484840514171615612b29579050905005056105805180820281191515600160ff1b8414151782158484840514171615612b295790509050056107e05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610800526108005160008112612b295761082052610600516107e051670de0b6b3a7640000810281670de0b6b3a7640000820518612b295790500560008112612b29576108405260a43561082051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050046104e052662386f26fc0ffff6104e0511015610fd8576000610fe9565b68056bc75e2d631000006104e05111155b611053576012610860527f556e736166652076616c756520666f72207900000000000000000000000000006108805261086050610860518061088001601f826000031636823750506308c379a061082052602061084052601f19601f61086051011660440161083cfd5b60406108205bf35b63bad1dc268118611aee57606436103417612b295760206060600461016037611085610200612732565b610200f3611aee565b637b12e0098118611aee5760c436103417612b295760a435610200525b606060446040376110bd610280611af4565b610280805161022052602081015161024052604081015161026052507901f20fe5212d2319f8671d495c8ba43b5b4b98d506d374fd487a6102205111612b29576102205115612b295761026051610240516102205101016102805260006102a052610200516111595761022051610160526102405161018052610260516101a0526111496102c0612732565b6102c0516003026102a052611303565b6ec097ce7bc90715b34b9f100000000161028051101561127a5769d3c21bcecceda10000016102805110156111f65761020051670de0b6b3a76400006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b2957905060c0526111e96102c0612525565b6102c0516102a052611303565b6102005169d3c21bcecceda10000006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b29579050620f4240810281620f4240820418612b2957905060c05261126d6102c0612525565b6102c0516102a052611303565b610200516ec097ce7bc90715b34b9f10000000006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b2957905064e8d4a5100081028164e8d4a51000820418612b2957905060c0526112fa6102c0612525565b6102c0516102a0525b610140366102c037600060ff905b80610400526102a0516103a0526102a0516003610260516102a0516003610240516102a051600361022051670de0b6b3a76400000202040202040202046102c052670de0b6b3a7640000602435016102e0526102c0516102e051116113855760016102e0516102c05103016102e052611396565b60016102c0516102e05103016102e0525b6004356127106102e0516024356102e0516024356102a051670de0b6b3a764000002040204020204610300526102e0516102c0516753444835ec580000020461032052670de0b6b3a76400006102a0516103205102046102c0516003610300510204670de0b6b3a7640000610320516102805102046102805101010361034052610340516102a051610280516103405101808202811583838304141715612b2957905090500461036052610340516102a0516102a051808202811583838304141715612b2957905090500461038052670de0b6b3a763ffff6102c05111156114d257610380516102c051670de0b6b3a76400006102c05103670de0b6b3a76400006102a051610340516103005104808202811583838304141715612b295790509050040204808203828111612b29579050905061038052611528565b610380516102c0516102c051670de0b6b3a764000003670de0b6b3a76400006102a051610340516103005104808202811583838304141715612b295790509050040204808201828110612b295790509050610380525b61038051610360511161154a5761036051610380510360011c6102a052611558565b6103805161036051036102a0525b6103a0516102a05111611577576102a0516103a051036103c052611585565b6103a0516102a051036103c0525b6102a05180662386f26fc10000811882662386f26fc100001102189050655af3107a40006103c05102101561168a5760006003905b8060051b6102200151610420526102a051670de0b6b3a76400006104205102046103e052662386f26fc0ffff6103e05110156115f7576000611608565b68056bc75e2d631000006103e05111155b611672576012610440527f556e736166652076616c75657320785b695d00000000000000000000000000006104605261044050610440518061046001601f826000031636823750506308c379a061040052602061042052601f19601f61044051011660440161041cfd5b6001018181186115ba575050505060206102a06116fc565b6001018181186113115750506010610400527f446964206e6f7420636f6e7665726765000000000000000000000000000000006104205261040050610400518061042001601f826000031636823750506308c379a06103c05260206103e052601f19601f6104005101166044016103dcfd5bf3611aee565b63754b76b38118611aee5760c436103417612b295767016345785d8a00006064351015611730576000611745565b6d314dc6448d9338c15b0a0000000060643511155b15612b2957606435606435606435600435601b810281601b820418612b29579050602435808202811583838304141715612b29579050905004604435808202811583838304141715612b295790509050046ec097ce7bc90715b34b9f10000000008102816ec097ce7bc90715b34b9f1000000000820418612b29579050046040526ec097ce7bc90715b34b9f10000000006ec097ce7bc90715b34b9f10000000006040518060011b818160011c18612b29579050604051808202811583838304141715612b29579050905004604051808202811583838304141715612b295790509050046002670de0b6b3a764000060a435010a808201828110612b295790509050670de0b6b3a76400006ec097ce7bc90715b34b9f100000000060026040510a046729a2241af62c000060a43560011b01808202811583838304141715612b29579050905004808203828111612b295790509050606052612710600260a4350a60843502046080526060516ec097ce7bc90715b34b9f1000000000606435608051600435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b29579050905060a05260a0516004356060516ec097ce7bc90715b34b9f1000000000606435608051602435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b295790509050808202811583838304141715612b2957905090506024358015612b295780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790500460c05260a0516004356060516ec097ce7bc90715b34b9f1000000000606435608051604435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b295790509050808202811583838304141715612b2957905090506044358015612b295780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790500460e052604060c0f3611aee565b63f42c56c28118611aee57602436103417612b2957602060043560c052611a80610160612525565b610160f3611aee565b63fa18042d8118611aee57608436103417612b295760206060600460403760643560a052611ab86101006127ac565b610100f3611aee565b6381d18d878118611aee57602436103417612b29576020600435604052611ae96101206128d4565b610120f35b60006000fd5b60405160a05260605160c05260805160e05260a0516101005260c05160a0511015611b275760c05160a0526101005160c0525b60e05160a0511015611b485760a0516101005260e05160a0526101005160e0525b60e05160c0511015611b695760c0516101005260e05160c0526101005160e0525b60a051815260c051602082015260e051604082015250565b60006102005260006003905b80610220526101e0516102205114611c7a576102205160028111612b295760051b6101600151670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790506101c0518015612b29578082049050905061020052662386f26fc10000610200511015611bff576000611c10565b68056bc75e2d631000006102005111155b611c7a576012610240527f556e736166652076616c75657320785b695d00000000000000000000000000006102605261024050610240518061026001601f826000031636823750506308c379a061020052602061022052601f19601f61024051011660440161021cfd5b600101818118611b8d5750506101c05160038104905061022052670de0b6b3a7640000610240526000610260526101605161028052610180516102a0526101a0516102c05260006101e05160028111612b295760051b6102800152610280516040526102a0516060526102c051608052611cf56102e0611af4565b6102e0805161034052602081015161036052604081015161038052506103405161028052610360516102a052610380516102c05261028051655af3107a4000810490506101c051655af3107a40008104905080828118828411021890509050606481811860648311021890506102e052600260028101905b8061030052610300518060030360038111612b2957905060028111612b295760051b610280015161032052610220516101c051808202811583838304141715612b2957905090506103205160038102816003820418612b295790508015612b295780820490509050610220526102605161032051808201828110612b29579050905061026052600101818118611d6d57505060006002905b8061030052610240516103005160028111612b295760051b6102800151808202811583838304141715612b29579050905060038102816003820418612b295790506101c0518015612b29578082049050905061024052600101818118611e055750506101803661030037600060ff905b806104805261022051610320526102405161022051808202811583838304141715612b29579050905060038102816003820418612b295790506101c0518015612b295780820490509050610340526102605161022051808201828110612b2957905090506103605261014051670de0b6b3a76400008101818110612b2957905061038052610340516103805111611f32576103405161038051808203828111612b29579050905060018101818110612b2957905061038052611f5a565b6103805161034051808203828111612b29579050905060018101818110612b29579050610380525b6101c051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610140518015612b29578082049050905061038051808202811583838304141715612b295790509050610140518015612b29578082049050905061038051808202811583838304141715612b295790509050612710810281612710820418612b29579050610120518015612b2957808204905090506103a05261034051671bc16d674ec80000810281671bc16d674ec80000820418612b29579050610380518015612b29578082049050905080670de0b6b3a764000001670de0b6b3a76400008110612b295790506103c05261022051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610360516103c051808202811583838304141715612b295790509050808201828110612b2957905090506103a051808201828110612b2957905090506103e0526101c0516103c051808202811583838304141715612b29579050905061040052610400516103e051106120f6576103e05161040051808203828111612b2957905090506103e052612109565b610320518060011c905061022052612393565b6103e051610220518015612b295780820490509050610420526103a051610420518015612b295780820490509050610440526103e0516101c051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050808201828110612b295790509050610420518015612b29578082049050905061044051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610340518015612b295780820490509050808201828110612b295790509050610460526104405161036051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610420518015612b295780820490509050808201828110612b2957905090506104405261044051610460511061223a576104605161044051808203828111612b29579050905061022052612249565b610320518060011c9050610220525b610320516102205111612275576103205161022051808203828111612b29579050905061030052612290565b6102205161032051808203828111612b295790509050610300525b6102e05161022051655af3107a400081049050808281188284110218905090506103005110156123935761022051670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790506101c0518015612b29578082049050905061020052662386f26fc1000061020051101561230a57600061231b565b68056bc75e2d631000006102005111155b6123855760126104a0527f556e736166652076616c756520666f72207900000000000000000000000000006104c0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b610220518352505050612405565b600101818118611e755750506010610480527f446964206e6f7420636f6e7665726765000000000000000000000000000000006104a0526104805061048051806104a001601f826000031636823750506308c379a061044052602061046052601f19601f61048051011660440161045cfd5b565b604051608052600060a05260405160801c1561242c5760405160801c608052608060a0525b60805160401c1561244a5760805160401c608052604060a0510160a0525b60805160201c156124685760805160201c608052602060a0510160a0525b60805160101c156124865760805160101c608052601060a0510160a0525b60805160081c156124a45760805160081c608052600860a0510160a0525b60805160041c156124c25760805160041c608052600460a0510160a0525b60805160021c156124e05760805160021c608052600260a0510160a0525b60805160011c156124f557600160a0510160a0525b60605161250357600061250e565b604051600160a0511b105b1561251d57600160a0510160a0525b60a051815250565b600060e0527812725dd1d243aba0e75fe645cc4873f9e64d542c5db234000060c051101561259a57710154484932d2e725a5bbca17a3aba173d3d560c0511015612585576ec097ce7bc90715b34b9f100000000060c0510260e0526125a1565b670de0b6b3a764000060c0510260e0526125a1565b60c05160e0525b60e05160405260006060526125b7610120612407565b610120518060ff1c612b2957610100526101005160008112612b295760038106905061012052610120516103e80a610120516104ec0a60036101005160008112612b29570460020a020461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b0104610140527812725dd1d243aba0e75fe645cc4873f9e64d542c5db234000060c051101561271957710154484932d2e725a5bbca17a3aba173d3d560c0511061272957620f4240610140510261014052612729565b64e8d4a510006101405102610140525b61014051815250565b670de0b6b3a7640000670de0b6b3a76400006101605161018051808202811583838304141715612b295790509050046101a051808202811583838304141715612b295790509050046101c0526101c0516127905760008152506127aa565b6101c05160c0526127a26101e0612525565b6101e0518152505b565b604051606051808201828110612b295790509050608051808201828110612b29579050905060c0526040516729a2241af62c00008102816729a2241af62c0000820418612b2957905060c0518015612b29578082049050905060e05260c05160e05160038102816003820418612b29579050606051808202811583838304141715612b2957905090500460e05260c05160e05160038102816003820418612b29579050608051808202811583838304141715612b2957905090500460e05260a051156128cc5760a051670de0b6b3a7640000810281670de0b6b3a7640000820418612b2957905060a051670de0b6b3a76400008101818110612b2957905060e051808203828111612b2957905090508015612b29578082049050905060e0525b60e051815250565b6040516060527ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c16040511361290d576000815250612b27565b680755bf798b4a1bf1e4604051131561297d5760106080527f7761645f657870206f766572666c6f770000000000000000000000000000000060a0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6503782dace9d9604051604e1b056060526b8000000000000000000000006bb17217f7d1cf79abc9e3b39860605160601b050160601d6080526bb17217f7d1cf79abc9e3b39860805102606051036060526d02d16720577bd19bf614176fe9ea6060516c10fe68e7fd37d0007b713f7650606051010260601d0160a05279d835ebba824c98fb31b83b2ca45c0000000000000000000000006060516e0587f503bb6ea29d25fcb74019645060a0516d04a4fd9f2a8b96949216d2255a6c60605160a05101030260601d01020160c0526d0277594991cfc85f6e2461837cd96060516c240c330e9fb2d9cbaf0fd5aafc606051030260601d0160e0526d1a521255e34f6a5061b25ef1c9c460605160e0510260601d0360e0526db1bbb201f443cf962f1a1d3db4a560605160e0510260601d0160e0526e02c72388d9f74f51a9331fed693f1560605160e0510260601d0360e0526e05180bb14799ab47a8a8cb2a527d5760605160e0510260601d0160e05260e05160c051056101005274029d9dc38563c32e5c2f6dc192ee70ef65f9978af3610100510260805160c30360008112612b29571c8152505b565b600080fd001a108e1a5817021aee1a8900bd1ac184192b3e811000a16576797065728300030a0014

Deployed Bytecode

0x60003560e01c60026007821660011b612b2e01601e39600051565b6354fd4d5081186100995734612b295760208060805260066040527f76322e302e30000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f82600003163682375050601f19601f8251602001011690509050810190506080f35b63c7fab7088118611aee5760a436103417612b29576000610200526110ab56611aee565b634a2ab3be811861105b5760e436103417612b2957610a8c60043510156100e55760006100f0565b631017df8060043511155b15612b29576402540be400602435101561010b576000610119565b66b1a2bc2ec5000060243511155b15612b295767016345785d8a000060a435101561013757600061014c565b6d314dc6448d9338c15b0a0000000060a43511155b15612b295760006104e05260006003905b806105005260c4356105005114610247576105005160028111612b295760051b60440135670de0b6b3a7640000810281670de0b6b3a7640000820418612b2957905060a4358015612b2957808204905090506104e052662386f26fc100006104e05110156101cc5760006101dd565b68056bc75e2d631000006104e05111155b610247576012610520527f556e736166652076616c75657320785b695d00000000000000000000000000006105405261052050610520518061054001601f826000031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b60010181811861015d5750506040366105003760c435610272576001610500526002610520526102a4565b600160c4351861028d576000610500526002610520526102a4565b600260c435186102a4576000610500526001610520525b6004358060ff1c612b2957610540526024358060ff1c612b29576105605260a4358060ff1c612b2957610580526105005160028111612b295760051b604401358060ff1c612b29576105a0526105205160028111612b295760051b604401358060ff1c612b29576105c0526105605161056051026105e0526e0722112107720a4902cd0097b425ed61060052601b61056051671bc16d674ec8000002056e1566336316561edb086701c71c71c7016105c0516127106102d96105e0516105a05161058051610580510205026105405180820281191515600160ff1b8414151782158484840514171615612b2957905090500505058082038281136000831218612b29579050905061062052601b673782dace9d90000061056051016105605102056e1566336316561edb086701c71c71c701612710601b61054051610580516105e051610580516105c0516105a051010380820281191515600160ff1b8414151782158484840514171615612b295790509050050205058082018281126000831218612b29579050905061064052601b61056051670de0b6b3a7640000016fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a90500561066052610600516003026106405180820281191515600160ff1b8414151782158484840514171615612b295790509050610620518015612b2957808205600160ff1b8314156000198314151715612b295790509050610620518082038281136000831218612b2957905090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811315610520578061052f565b806000038114612b2957806000035b90506106805260006106a05273af298d050e4395d69670b12b7f410000000000016106805112156106845772047bf19673df52e37f2410011d10000000000161068051121561066f57701d6329f1c35ca4bfabb9f561000000000161068051121561065b576ec097ce7bc90715b34b9f1000000001610680511215610649576d04ee2d6d415b85acef8100000001610680511215610639576b204fce5e3e2502611000000161068051121561062a5769d3c21bcecceda100000161068051121561061d5768056bc75e2d631000016106805112156106125760016106a052610697565b60646106a052610697565b620f42406106a052610697565b6402540be4006106a052610697565b655af3107a40006106a052610697565b670de0b6b3a76400006106a052610697565b69021e19e0c9bab24000006106a052610697565b6a52b7d2dcc80cd2e40000006106a052610697565b6c0c9f2c9cd04674edea400000006106a0525b60006106c052610620517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156106cf57806106de565b806000038114612b2957806000035b9050610600517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156107125780610721565b806000038114612b2957806000035b9050136107e1576106005161062051057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81131561075f578061076e565b806000038114612b2957806000035b90506106c0526106a051610600516106c0518015612b2957808205600160ff1b8314156000198314151715612b29579050905005610600526106a0516106c051610620510505610620526106a0516106c051610640510505610640526106a0516106c051610660510505610660526108d9565b6106205161060051057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156108185780610827565b806000038114612b2957806000035b90506106c0526106a0516106c051610600510205610600526106a051610620516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610620526106a051610640516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610640526106a051610660516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610660525b610600516003026106405180820281191515600160ff1b8414151782158484840514171615612b2957905090506106e052610620516106e05105610620518082038281136000831218612b29579050905061070052610620516106e05160038102816003820518612b29579050056106205160011b8082038281136000831218612b2957905090506106205161062051610600516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a9050601b810281601b820518612b29579050056106605180820281191515600160ff1b8414151782158484840514171615612b295790509050058082038281136000831218612b29579050905061072052610720516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a905061062051610700516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a90508060021b816004820518612b29579050056107005180820281191515600160ff1b8414151782158484840514171615612b2957905090508082018281126000831218612b295790509050610740526000610760526001610740511215610b2d5760406004610120376060604461016037604060a46101c037610b11610780611b81565b610780516107a05260006107c05260406107a061105956610c26565b6107405160008112612b29578060b5710100000000000000000000000000000000008210610b62578160801c91508060401b90505b69010000000000000000008210610b80578160401c91508060201b90505b650100000000008210610b9a578160201c91508060101b90505b63010000008210610bb2578160101c91508060081b90505b620100008201810260121c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c905080830480828118828410021890509050905090508060ff1c612b2957610760525b6000610780526000610620511215610cbb57610620517f80000000000000000000000000000000000000000000000000000000000000008114612b295760000360008112612b295760c052610c7c6107a0612525565b6107a0518060ff1c612b29577f80000000000000000000000000000000000000000000000000000000000000008114612b295760000361078052610ce6565b6106205160008112612b295760c052610cd56107a0612525565b6107a0518060ff1c612b2957610780525b60006107a0526001610720511215610d955761072051610760518082038281136000831218612b2957905090507f80000000000000000000000000000000000000000000000000000000000000008114612b295760000360008112612b295760011c60c052610d566107c0612525565b6107c0518060ff1c612b29577f80000000000000000000000000000000000000000000000000000000000000008114612b29576000036107a052610dda565b61072051610760518082018281126000831218612b29579050905060008112612b295760011c60c052610dc96107c0612525565b6107c0518060ff1c612b29576107a0525b670de0b6b3a7640000670de0b6b3a7640000610780516107805180820281191515600160ff1b8414151782158484840514171615612b295790509050056107a05180820281191515600160ff1b8414151782158484840514171615612b295790509050056107c052600361062051610620516107005180820281191515600160ff1b8414151782158484840514171615612b2957905090506107c0518015612b2957808205600160ff1b8314156000198314151715612b2957905090508082018281126000831218612b2957905090506107c0518082038281136000831218612b295790509050056107e052610600516105a0516105c051601b610580516105805180820281191515600160ff1b8414151782158484840514171615612b29579050905005056105805180820281191515600160ff1b8414151782158484840514171615612b295790509050056107e05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610800526108005160008112612b295761082052610600516107e051670de0b6b3a7640000810281670de0b6b3a7640000820518612b295790500560008112612b29576108405260a43561082051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050046104e052662386f26fc0ffff6104e0511015610fd8576000610fe9565b68056bc75e2d631000006104e05111155b611053576012610860527f556e736166652076616c756520666f72207900000000000000000000000000006108805261086050610860518061088001601f826000031636823750506308c379a061082052602061084052601f19601f61086051011660440161083cfd5b60406108205bf35b63bad1dc268118611aee57606436103417612b295760206060600461016037611085610200612732565b610200f3611aee565b637b12e0098118611aee5760c436103417612b295760a435610200525b606060446040376110bd610280611af4565b610280805161022052602081015161024052604081015161026052507901f20fe5212d2319f8671d495c8ba43b5b4b98d506d374fd487a6102205111612b29576102205115612b295761026051610240516102205101016102805260006102a052610200516111595761022051610160526102405161018052610260516101a0526111496102c0612732565b6102c0516003026102a052611303565b6ec097ce7bc90715b34b9f100000000161028051101561127a5769d3c21bcecceda10000016102805110156111f65761020051670de0b6b3a76400006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b2957905060c0526111e96102c0612525565b6102c0516102a052611303565b6102005169d3c21bcecceda10000006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b29579050620f4240810281620f4240820418612b2957905060c05261126d6102c0612525565b6102c0516102a052611303565b610200516ec097ce7bc90715b34b9f10000000006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b2957905064e8d4a5100081028164e8d4a51000820418612b2957905060c0526112fa6102c0612525565b6102c0516102a0525b610140366102c037600060ff905b80610400526102a0516103a0526102a0516003610260516102a0516003610240516102a051600361022051670de0b6b3a76400000202040202040202046102c052670de0b6b3a7640000602435016102e0526102c0516102e051116113855760016102e0516102c05103016102e052611396565b60016102c0516102e05103016102e0525b6004356127106102e0516024356102e0516024356102a051670de0b6b3a764000002040204020204610300526102e0516102c0516753444835ec580000020461032052670de0b6b3a76400006102a0516103205102046102c0516003610300510204670de0b6b3a7640000610320516102805102046102805101010361034052610340516102a051610280516103405101808202811583838304141715612b2957905090500461036052610340516102a0516102a051808202811583838304141715612b2957905090500461038052670de0b6b3a763ffff6102c05111156114d257610380516102c051670de0b6b3a76400006102c05103670de0b6b3a76400006102a051610340516103005104808202811583838304141715612b295790509050040204808203828111612b29579050905061038052611528565b610380516102c0516102c051670de0b6b3a764000003670de0b6b3a76400006102a051610340516103005104808202811583838304141715612b295790509050040204808201828110612b295790509050610380525b61038051610360511161154a5761036051610380510360011c6102a052611558565b6103805161036051036102a0525b6103a0516102a05111611577576102a0516103a051036103c052611585565b6103a0516102a051036103c0525b6102a05180662386f26fc10000811882662386f26fc100001102189050655af3107a40006103c05102101561168a5760006003905b8060051b6102200151610420526102a051670de0b6b3a76400006104205102046103e052662386f26fc0ffff6103e05110156115f7576000611608565b68056bc75e2d631000006103e05111155b611672576012610440527f556e736166652076616c75657320785b695d00000000000000000000000000006104605261044050610440518061046001601f826000031636823750506308c379a061040052602061042052601f19601f61044051011660440161041cfd5b6001018181186115ba575050505060206102a06116fc565b6001018181186113115750506010610400527f446964206e6f7420636f6e7665726765000000000000000000000000000000006104205261040050610400518061042001601f826000031636823750506308c379a06103c05260206103e052601f19601f6104005101166044016103dcfd5bf3611aee565b63754b76b38118611aee5760c436103417612b295767016345785d8a00006064351015611730576000611745565b6d314dc6448d9338c15b0a0000000060643511155b15612b2957606435606435606435600435601b810281601b820418612b29579050602435808202811583838304141715612b29579050905004604435808202811583838304141715612b295790509050046ec097ce7bc90715b34b9f10000000008102816ec097ce7bc90715b34b9f1000000000820418612b29579050046040526ec097ce7bc90715b34b9f10000000006ec097ce7bc90715b34b9f10000000006040518060011b818160011c18612b29579050604051808202811583838304141715612b29579050905004604051808202811583838304141715612b295790509050046002670de0b6b3a764000060a435010a808201828110612b295790509050670de0b6b3a76400006ec097ce7bc90715b34b9f100000000060026040510a046729a2241af62c000060a43560011b01808202811583838304141715612b29579050905004808203828111612b295790509050606052612710600260a4350a60843502046080526060516ec097ce7bc90715b34b9f1000000000606435608051600435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b29579050905060a05260a0516004356060516ec097ce7bc90715b34b9f1000000000606435608051602435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b295790509050808202811583838304141715612b2957905090506024358015612b295780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790500460c05260a0516004356060516ec097ce7bc90715b34b9f1000000000606435608051604435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b295790509050808202811583838304141715612b2957905090506044358015612b295780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790500460e052604060c0f3611aee565b63f42c56c28118611aee57602436103417612b2957602060043560c052611a80610160612525565b610160f3611aee565b63fa18042d8118611aee57608436103417612b295760206060600460403760643560a052611ab86101006127ac565b610100f3611aee565b6381d18d878118611aee57602436103417612b29576020600435604052611ae96101206128d4565b610120f35b60006000fd5b60405160a05260605160c05260805160e05260a0516101005260c05160a0511015611b275760c05160a0526101005160c0525b60e05160a0511015611b485760a0516101005260e05160a0526101005160e0525b60e05160c0511015611b695760c0516101005260e05160c0526101005160e0525b60a051815260c051602082015260e051604082015250565b60006102005260006003905b80610220526101e0516102205114611c7a576102205160028111612b295760051b6101600151670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790506101c0518015612b29578082049050905061020052662386f26fc10000610200511015611bff576000611c10565b68056bc75e2d631000006102005111155b611c7a576012610240527f556e736166652076616c75657320785b695d00000000000000000000000000006102605261024050610240518061026001601f826000031636823750506308c379a061020052602061022052601f19601f61024051011660440161021cfd5b600101818118611b8d5750506101c05160038104905061022052670de0b6b3a7640000610240526000610260526101605161028052610180516102a0526101a0516102c05260006101e05160028111612b295760051b6102800152610280516040526102a0516060526102c051608052611cf56102e0611af4565b6102e0805161034052602081015161036052604081015161038052506103405161028052610360516102a052610380516102c05261028051655af3107a4000810490506101c051655af3107a40008104905080828118828411021890509050606481811860648311021890506102e052600260028101905b8061030052610300518060030360038111612b2957905060028111612b295760051b610280015161032052610220516101c051808202811583838304141715612b2957905090506103205160038102816003820418612b295790508015612b295780820490509050610220526102605161032051808201828110612b29579050905061026052600101818118611d6d57505060006002905b8061030052610240516103005160028111612b295760051b6102800151808202811583838304141715612b29579050905060038102816003820418612b295790506101c0518015612b29578082049050905061024052600101818118611e055750506101803661030037600060ff905b806104805261022051610320526102405161022051808202811583838304141715612b29579050905060038102816003820418612b295790506101c0518015612b295780820490509050610340526102605161022051808201828110612b2957905090506103605261014051670de0b6b3a76400008101818110612b2957905061038052610340516103805111611f32576103405161038051808203828111612b29579050905060018101818110612b2957905061038052611f5a565b6103805161034051808203828111612b29579050905060018101818110612b29579050610380525b6101c051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610140518015612b29578082049050905061038051808202811583838304141715612b295790509050610140518015612b29578082049050905061038051808202811583838304141715612b295790509050612710810281612710820418612b29579050610120518015612b2957808204905090506103a05261034051671bc16d674ec80000810281671bc16d674ec80000820418612b29579050610380518015612b29578082049050905080670de0b6b3a764000001670de0b6b3a76400008110612b295790506103c05261022051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610360516103c051808202811583838304141715612b295790509050808201828110612b2957905090506103a051808201828110612b2957905090506103e0526101c0516103c051808202811583838304141715612b29579050905061040052610400516103e051106120f6576103e05161040051808203828111612b2957905090506103e052612109565b610320518060011c905061022052612393565b6103e051610220518015612b295780820490509050610420526103a051610420518015612b295780820490509050610440526103e0516101c051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050808201828110612b295790509050610420518015612b29578082049050905061044051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610340518015612b295780820490509050808201828110612b295790509050610460526104405161036051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610420518015612b295780820490509050808201828110612b2957905090506104405261044051610460511061223a576104605161044051808203828111612b29579050905061022052612249565b610320518060011c9050610220525b610320516102205111612275576103205161022051808203828111612b29579050905061030052612290565b6102205161032051808203828111612b295790509050610300525b6102e05161022051655af3107a400081049050808281188284110218905090506103005110156123935761022051670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790506101c0518015612b29578082049050905061020052662386f26fc1000061020051101561230a57600061231b565b68056bc75e2d631000006102005111155b6123855760126104a0527f556e736166652076616c756520666f72207900000000000000000000000000006104c0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b610220518352505050612405565b600101818118611e755750506010610480527f446964206e6f7420636f6e7665726765000000000000000000000000000000006104a0526104805061048051806104a001601f826000031636823750506308c379a061044052602061046052601f19601f61048051011660440161045cfd5b565b604051608052600060a05260405160801c1561242c5760405160801c608052608060a0525b60805160401c1561244a5760805160401c608052604060a0510160a0525b60805160201c156124685760805160201c608052602060a0510160a0525b60805160101c156124865760805160101c608052601060a0510160a0525b60805160081c156124a45760805160081c608052600860a0510160a0525b60805160041c156124c25760805160041c608052600460a0510160a0525b60805160021c156124e05760805160021c608052600260a0510160a0525b60805160011c156124f557600160a0510160a0525b60605161250357600061250e565b604051600160a0511b105b1561251d57600160a0510160a0525b60a051815250565b600060e0527812725dd1d243aba0e75fe645cc4873f9e64d542c5db234000060c051101561259a57710154484932d2e725a5bbca17a3aba173d3d560c0511015612585576ec097ce7bc90715b34b9f100000000060c0510260e0526125a1565b670de0b6b3a764000060c0510260e0526125a1565b60c05160e0525b60e05160405260006060526125b7610120612407565b610120518060ff1c612b2957610100526101005160008112612b295760038106905061012052610120516103e80a610120516104ec0a60036101005160008112612b29570460020a020461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b0104610140527812725dd1d243aba0e75fe645cc4873f9e64d542c5db234000060c051101561271957710154484932d2e725a5bbca17a3aba173d3d560c0511061272957620f4240610140510261014052612729565b64e8d4a510006101405102610140525b61014051815250565b670de0b6b3a7640000670de0b6b3a76400006101605161018051808202811583838304141715612b295790509050046101a051808202811583838304141715612b295790509050046101c0526101c0516127905760008152506127aa565b6101c05160c0526127a26101e0612525565b6101e0518152505b565b604051606051808201828110612b295790509050608051808201828110612b29579050905060c0526040516729a2241af62c00008102816729a2241af62c0000820418612b2957905060c0518015612b29578082049050905060e05260c05160e05160038102816003820418612b29579050606051808202811583838304141715612b2957905090500460e05260c05160e05160038102816003820418612b29579050608051808202811583838304141715612b2957905090500460e05260a051156128cc5760a051670de0b6b3a7640000810281670de0b6b3a7640000820418612b2957905060a051670de0b6b3a76400008101818110612b2957905060e051808203828111612b2957905090508015612b29578082049050905060e0525b60e051815250565b6040516060527ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c16040511361290d576000815250612b27565b680755bf798b4a1bf1e4604051131561297d5760106080527f7761645f657870206f766572666c6f770000000000000000000000000000000060a0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6503782dace9d9604051604e1b056060526b8000000000000000000000006bb17217f7d1cf79abc9e3b39860605160601b050160601d6080526bb17217f7d1cf79abc9e3b39860805102606051036060526d02d16720577bd19bf614176fe9ea6060516c10fe68e7fd37d0007b713f7650606051010260601d0160a05279d835ebba824c98fb31b83b2ca45c0000000000000000000000006060516e0587f503bb6ea29d25fcb74019645060a0516d04a4fd9f2a8b96949216d2255a6c60605160a05101030260601d01020160c0526d0277594991cfc85f6e2461837cd96060516c240c330e9fb2d9cbaf0fd5aafc606051030260601d0160e0526d1a521255e34f6a5061b25ef1c9c460605160e0510260601d0360e0526db1bbb201f443cf962f1a1d3db4a560605160e0510260601d0160e0526e02c72388d9f74f51a9331fed693f1560605160e0510260601d0360e0526e05180bb14799ab47a8a8cb2a527d5760605160e0510260601d0160e05260e05160c051056101005274029d9dc38563c32e5c2f6dc192ee70ef65f9978af3610100510260805160c30360008112612b29571c8152505b565b600080fd001a108e1a5817021aee1a8900bd1ac1

Block Transaction 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

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.