Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
CurveTricryptoMathOptimized
Compiler Version
vyper:0.3.10
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
- No Contract Security Audit Submitted- Submit Audit Here
[{"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"}]}]
Contract Creation Code
612b3e61001161000039612b3e610000f360003560e01c60026007821660011b612b2e01601e39600051565b6354fd4d5081186100995734612b295760208060805260066040527f76322e302e30000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f82600003163682375050601f19601f8251602001011690509050810190506080f35b63c7fab7088118611aee5760a436103417612b29576000610200526110ab56611aee565b634a2ab3be811861105b5760e436103417612b2957610a8c60043510156100e55760006100f0565b631017df8060043511155b15612b29576402540be400602435101561010b576000610119565b66b1a2bc2ec5000060243511155b15612b295767016345785d8a000060a435101561013757600061014c565b6d314dc6448d9338c15b0a0000000060a43511155b15612b295760006104e05260006003905b806105005260c4356105005114610247576105005160028111612b295760051b60440135670de0b6b3a7640000810281670de0b6b3a7640000820418612b2957905060a4358015612b2957808204905090506104e052662386f26fc100006104e05110156101cc5760006101dd565b68056bc75e2d631000006104e05111155b610247576012610520527f556e736166652076616c75657320785b695d00000000000000000000000000006105405261052050610520518061054001601f826000031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b60010181811861015d5750506040366105003760c435610272576001610500526002610520526102a4565b600160c4351861028d576000610500526002610520526102a4565b600260c435186102a4576000610500526001610520525b6004358060ff1c612b2957610540526024358060ff1c612b29576105605260a4358060ff1c612b2957610580526105005160028111612b295760051b604401358060ff1c612b29576105a0526105205160028111612b295760051b604401358060ff1c612b29576105c0526105605161056051026105e0526e0722112107720a4902cd0097b425ed61060052601b61056051671bc16d674ec8000002056e1566336316561edb086701c71c71c7016105c0516127106102d96105e0516105a05161058051610580510205026105405180820281191515600160ff1b8414151782158484840514171615612b2957905090500505058082038281136000831218612b29579050905061062052601b673782dace9d90000061056051016105605102056e1566336316561edb086701c71c71c701612710601b61054051610580516105e051610580516105c0516105a051010380820281191515600160ff1b8414151782158484840514171615612b295790509050050205058082018281126000831218612b29579050905061064052601b61056051670de0b6b3a7640000016fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a90500561066052610600516003026106405180820281191515600160ff1b8414151782158484840514171615612b295790509050610620518015612b2957808205600160ff1b8314156000198314151715612b295790509050610620518082038281136000831218612b2957905090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811315610520578061052f565b806000038114612b2957806000035b90506106805260006106a05273af298d050e4395d69670b12b7f410000000000016106805112156106845772047bf19673df52e37f2410011d10000000000161068051121561066f57701d6329f1c35ca4bfabb9f561000000000161068051121561065b576ec097ce7bc90715b34b9f1000000001610680511215610649576d04ee2d6d415b85acef8100000001610680511215610639576b204fce5e3e2502611000000161068051121561062a5769d3c21bcecceda100000161068051121561061d5768056bc75e2d631000016106805112156106125760016106a052610697565b60646106a052610697565b620f42406106a052610697565b6402540be4006106a052610697565b655af3107a40006106a052610697565b670de0b6b3a76400006106a052610697565b69021e19e0c9bab24000006106a052610697565b6a52b7d2dcc80cd2e40000006106a052610697565b6c0c9f2c9cd04674edea400000006106a0525b60006106c052610620517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156106cf57806106de565b806000038114612b2957806000035b9050610600517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156107125780610721565b806000038114612b2957806000035b9050136107e1576106005161062051057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81131561075f578061076e565b806000038114612b2957806000035b90506106c0526106a051610600516106c0518015612b2957808205600160ff1b8314156000198314151715612b29579050905005610600526106a0516106c051610620510505610620526106a0516106c051610640510505610640526106a0516106c051610660510505610660526108d9565b6106205161060051057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156108185780610827565b806000038114612b2957806000035b90506106c0526106a0516106c051610600510205610600526106a051610620516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610620526106a051610640516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610640526106a051610660516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610660525b610600516003026106405180820281191515600160ff1b8414151782158484840514171615612b2957905090506106e052610620516106e05105610620518082038281136000831218612b29579050905061070052610620516106e05160038102816003820518612b29579050056106205160011b8082038281136000831218612b2957905090506106205161062051610600516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a9050601b810281601b820518612b29579050056106605180820281191515600160ff1b8414151782158484840514171615612b295790509050058082038281136000831218612b29579050905061072052610720516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a905061062051610700516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a90508060021b816004820518612b29579050056107005180820281191515600160ff1b8414151782158484840514171615612b2957905090508082018281126000831218612b295790509050610740526000610760526001610740511215610b2d5760406004610120376060604461016037604060a46101c037610b11610780611b81565b610780516107a05260006107c05260406107a061105956610c26565b6107405160008112612b29578060b5710100000000000000000000000000000000008210610b62578160801c91508060401b90505b69010000000000000000008210610b80578160401c91508060201b90505b650100000000008210610b9a578160201c91508060101b90505b63010000008210610bb2578160101c91508060081b90505b620100008201810260121c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c905080830480828118828410021890509050905090508060ff1c612b2957610760525b6000610780526000610620511215610cbb57610620517f80000000000000000000000000000000000000000000000000000000000000008114612b295760000360008112612b295760c052610c7c6107a0612525565b6107a0518060ff1c612b29577f80000000000000000000000000000000000000000000000000000000000000008114612b295760000361078052610ce6565b6106205160008112612b295760c052610cd56107a0612525565b6107a0518060ff1c612b2957610780525b60006107a0526001610720511215610d955761072051610760518082038281136000831218612b2957905090507f80000000000000000000000000000000000000000000000000000000000000008114612b295760000360008112612b295760011c60c052610d566107c0612525565b6107c0518060ff1c612b29577f80000000000000000000000000000000000000000000000000000000000000008114612b29576000036107a052610dda565b61072051610760518082018281126000831218612b29579050905060008112612b295760011c60c052610dc96107c0612525565b6107c0518060ff1c612b29576107a0525b670de0b6b3a7640000670de0b6b3a7640000610780516107805180820281191515600160ff1b8414151782158484840514171615612b295790509050056107a05180820281191515600160ff1b8414151782158484840514171615612b295790509050056107c052600361062051610620516107005180820281191515600160ff1b8414151782158484840514171615612b2957905090506107c0518015612b2957808205600160ff1b8314156000198314151715612b2957905090508082018281126000831218612b2957905090506107c0518082038281136000831218612b295790509050056107e052610600516105a0516105c051601b610580516105805180820281191515600160ff1b8414151782158484840514171615612b29579050905005056105805180820281191515600160ff1b8414151782158484840514171615612b295790509050056107e05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610800526108005160008112612b295761082052610600516107e051670de0b6b3a7640000810281670de0b6b3a7640000820518612b295790500560008112612b29576108405260a43561082051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050046104e052662386f26fc0ffff6104e0511015610fd8576000610fe9565b68056bc75e2d631000006104e05111155b611053576012610860527f556e736166652076616c756520666f72207900000000000000000000000000006108805261086050610860518061088001601f826000031636823750506308c379a061082052602061084052601f19601f61086051011660440161083cfd5b60406108205bf35b63bad1dc268118611aee57606436103417612b295760206060600461016037611085610200612732565b610200f3611aee565b637b12e0098118611aee5760c436103417612b295760a435610200525b606060446040376110bd610280611af4565b610280805161022052602081015161024052604081015161026052507901f20fe5212d2319f8671d495c8ba43b5b4b98d506d374fd487a6102205111612b29576102205115612b295761026051610240516102205101016102805260006102a052610200516111595761022051610160526102405161018052610260516101a0526111496102c0612732565b6102c0516003026102a052611303565b6ec097ce7bc90715b34b9f100000000161028051101561127a5769d3c21bcecceda10000016102805110156111f65761020051670de0b6b3a76400006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b2957905060c0526111e96102c0612525565b6102c0516102a052611303565b6102005169d3c21bcecceda10000006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b29579050620f4240810281620f4240820418612b2957905060c05261126d6102c0612525565b6102c0516102a052611303565b610200516ec097ce7bc90715b34b9f10000000006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b2957905064e8d4a5100081028164e8d4a51000820418612b2957905060c0526112fa6102c0612525565b6102c0516102a0525b610140366102c037600060ff905b80610400526102a0516103a0526102a0516003610260516102a0516003610240516102a051600361022051670de0b6b3a76400000202040202040202046102c052670de0b6b3a7640000602435016102e0526102c0516102e051116113855760016102e0516102c05103016102e052611396565b60016102c0516102e05103016102e0525b6004356127106102e0516024356102e0516024356102a051670de0b6b3a764000002040204020204610300526102e0516102c0516753444835ec580000020461032052670de0b6b3a76400006102a0516103205102046102c0516003610300510204670de0b6b3a7640000610320516102805102046102805101010361034052610340516102a051610280516103405101808202811583838304141715612b2957905090500461036052610340516102a0516102a051808202811583838304141715612b2957905090500461038052670de0b6b3a763ffff6102c05111156114d257610380516102c051670de0b6b3a76400006102c05103670de0b6b3a76400006102a051610340516103005104808202811583838304141715612b295790509050040204808203828111612b29579050905061038052611528565b610380516102c0516102c051670de0b6b3a764000003670de0b6b3a76400006102a051610340516103005104808202811583838304141715612b295790509050040204808201828110612b295790509050610380525b61038051610360511161154a5761036051610380510360011c6102a052611558565b6103805161036051036102a0525b6103a0516102a05111611577576102a0516103a051036103c052611585565b6103a0516102a051036103c0525b6102a05180662386f26fc10000811882662386f26fc100001102189050655af3107a40006103c05102101561168a5760006003905b8060051b6102200151610420526102a051670de0b6b3a76400006104205102046103e052662386f26fc0ffff6103e05110156115f7576000611608565b68056bc75e2d631000006103e05111155b611672576012610440527f556e736166652076616c75657320785b695d00000000000000000000000000006104605261044050610440518061046001601f826000031636823750506308c379a061040052602061042052601f19601f61044051011660440161041cfd5b6001018181186115ba575050505060206102a06116fc565b6001018181186113115750506010610400527f446964206e6f7420636f6e7665726765000000000000000000000000000000006104205261040050610400518061042001601f826000031636823750506308c379a06103c05260206103e052601f19601f6104005101166044016103dcfd5bf3611aee565b63754b76b38118611aee5760c436103417612b295767016345785d8a00006064351015611730576000611745565b6d314dc6448d9338c15b0a0000000060643511155b15612b2957606435606435606435600435601b810281601b820418612b29579050602435808202811583838304141715612b29579050905004604435808202811583838304141715612b295790509050046ec097ce7bc90715b34b9f10000000008102816ec097ce7bc90715b34b9f1000000000820418612b29579050046040526ec097ce7bc90715b34b9f10000000006ec097ce7bc90715b34b9f10000000006040518060011b818160011c18612b29579050604051808202811583838304141715612b29579050905004604051808202811583838304141715612b295790509050046002670de0b6b3a764000060a435010a808201828110612b295790509050670de0b6b3a76400006ec097ce7bc90715b34b9f100000000060026040510a046729a2241af62c000060a43560011b01808202811583838304141715612b29579050905004808203828111612b295790509050606052612710600260a4350a60843502046080526060516ec097ce7bc90715b34b9f1000000000606435608051600435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b29579050905060a05260a0516004356060516ec097ce7bc90715b34b9f1000000000606435608051602435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b295790509050808202811583838304141715612b2957905090506024358015612b295780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790500460c05260a0516004356060516ec097ce7bc90715b34b9f1000000000606435608051604435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b295790509050808202811583838304141715612b2957905090506044358015612b295780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790500460e052604060c0f3611aee565b63f42c56c28118611aee57602436103417612b2957602060043560c052611a80610160612525565b610160f3611aee565b63fa18042d8118611aee57608436103417612b295760206060600460403760643560a052611ab86101006127ac565b610100f3611aee565b6381d18d878118611aee57602436103417612b29576020600435604052611ae96101206128d4565b610120f35b60006000fd5b60405160a05260605160c05260805160e05260a0516101005260c05160a0511015611b275760c05160a0526101005160c0525b60e05160a0511015611b485760a0516101005260e05160a0526101005160e0525b60e05160c0511015611b695760c0516101005260e05160c0526101005160e0525b60a051815260c051602082015260e051604082015250565b60006102005260006003905b80610220526101e0516102205114611c7a576102205160028111612b295760051b6101600151670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790506101c0518015612b29578082049050905061020052662386f26fc10000610200511015611bff576000611c10565b68056bc75e2d631000006102005111155b611c7a576012610240527f556e736166652076616c75657320785b695d00000000000000000000000000006102605261024050610240518061026001601f826000031636823750506308c379a061020052602061022052601f19601f61024051011660440161021cfd5b600101818118611b8d5750506101c05160038104905061022052670de0b6b3a7640000610240526000610260526101605161028052610180516102a0526101a0516102c05260006101e05160028111612b295760051b6102800152610280516040526102a0516060526102c051608052611cf56102e0611af4565b6102e0805161034052602081015161036052604081015161038052506103405161028052610360516102a052610380516102c05261028051655af3107a4000810490506101c051655af3107a40008104905080828118828411021890509050606481811860648311021890506102e052600260028101905b8061030052610300518060030360038111612b2957905060028111612b295760051b610280015161032052610220516101c051808202811583838304141715612b2957905090506103205160038102816003820418612b295790508015612b295780820490509050610220526102605161032051808201828110612b29579050905061026052600101818118611d6d57505060006002905b8061030052610240516103005160028111612b295760051b6102800151808202811583838304141715612b29579050905060038102816003820418612b295790506101c0518015612b29578082049050905061024052600101818118611e055750506101803661030037600060ff905b806104805261022051610320526102405161022051808202811583838304141715612b29579050905060038102816003820418612b295790506101c0518015612b295780820490509050610340526102605161022051808201828110612b2957905090506103605261014051670de0b6b3a76400008101818110612b2957905061038052610340516103805111611f32576103405161038051808203828111612b29579050905060018101818110612b2957905061038052611f5a565b6103805161034051808203828111612b29579050905060018101818110612b29579050610380525b6101c051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610140518015612b29578082049050905061038051808202811583838304141715612b295790509050610140518015612b29578082049050905061038051808202811583838304141715612b295790509050612710810281612710820418612b29579050610120518015612b2957808204905090506103a05261034051671bc16d674ec80000810281671bc16d674ec80000820418612b29579050610380518015612b29578082049050905080670de0b6b3a764000001670de0b6b3a76400008110612b295790506103c05261022051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610360516103c051808202811583838304141715612b295790509050808201828110612b2957905090506103a051808201828110612b2957905090506103e0526101c0516103c051808202811583838304141715612b29579050905061040052610400516103e051106120f6576103e05161040051808203828111612b2957905090506103e052612109565b610320518060011c905061022052612393565b6103e051610220518015612b295780820490509050610420526103a051610420518015612b295780820490509050610440526103e0516101c051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050808201828110612b295790509050610420518015612b29578082049050905061044051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610340518015612b295780820490509050808201828110612b295790509050610460526104405161036051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610420518015612b295780820490509050808201828110612b2957905090506104405261044051610460511061223a576104605161044051808203828111612b29579050905061022052612249565b610320518060011c9050610220525b610320516102205111612275576103205161022051808203828111612b29579050905061030052612290565b6102205161032051808203828111612b295790509050610300525b6102e05161022051655af3107a400081049050808281188284110218905090506103005110156123935761022051670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790506101c0518015612b29578082049050905061020052662386f26fc1000061020051101561230a57600061231b565b68056bc75e2d631000006102005111155b6123855760126104a0527f556e736166652076616c756520666f72207900000000000000000000000000006104c0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b610220518352505050612405565b600101818118611e755750506010610480527f446964206e6f7420636f6e7665726765000000000000000000000000000000006104a0526104805061048051806104a001601f826000031636823750506308c379a061044052602061046052601f19601f61048051011660440161045cfd5b565b604051608052600060a05260405160801c1561242c5760405160801c608052608060a0525b60805160401c1561244a5760805160401c608052604060a0510160a0525b60805160201c156124685760805160201c608052602060a0510160a0525b60805160101c156124865760805160101c608052601060a0510160a0525b60805160081c156124a45760805160081c608052600860a0510160a0525b60805160041c156124c25760805160041c608052600460a0510160a0525b60805160021c156124e05760805160021c608052600260a0510160a0525b60805160011c156124f557600160a0510160a0525b60605161250357600061250e565b604051600160a0511b105b1561251d57600160a0510160a0525b60a051815250565b600060e0527812725dd1d243aba0e75fe645cc4873f9e64d542c5db234000060c051101561259a57710154484932d2e725a5bbca17a3aba173d3d560c0511015612585576ec097ce7bc90715b34b9f100000000060c0510260e0526125a1565b670de0b6b3a764000060c0510260e0526125a1565b60c05160e0525b60e05160405260006060526125b7610120612407565b610120518060ff1c612b2957610100526101005160008112612b295760038106905061012052610120516103e80a610120516104ec0a60036101005160008112612b29570460020a020461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b0104610140527812725dd1d243aba0e75fe645cc4873f9e64d542c5db234000060c051101561271957710154484932d2e725a5bbca17a3aba173d3d560c0511061272957620f4240610140510261014052612729565b64e8d4a510006101405102610140525b61014051815250565b670de0b6b3a7640000670de0b6b3a76400006101605161018051808202811583838304141715612b295790509050046101a051808202811583838304141715612b295790509050046101c0526101c0516127905760008152506127aa565b6101c05160c0526127a26101e0612525565b6101e0518152505b565b604051606051808201828110612b295790509050608051808201828110612b29579050905060c0526040516729a2241af62c00008102816729a2241af62c0000820418612b2957905060c0518015612b29578082049050905060e05260c05160e05160038102816003820418612b29579050606051808202811583838304141715612b2957905090500460e05260c05160e05160038102816003820418612b29579050608051808202811583838304141715612b2957905090500460e05260a051156128cc5760a051670de0b6b3a7640000810281670de0b6b3a7640000820418612b2957905060a051670de0b6b3a76400008101818110612b2957905060e051808203828111612b2957905090508015612b29578082049050905060e0525b60e051815250565b6040516060527ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c16040511361290d576000815250612b27565b680755bf798b4a1bf1e4604051131561297d5760106080527f7761645f657870206f766572666c6f770000000000000000000000000000000060a0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6503782dace9d9604051604e1b056060526b8000000000000000000000006bb17217f7d1cf79abc9e3b39860605160601b050160601d6080526bb17217f7d1cf79abc9e3b39860805102606051036060526d02d16720577bd19bf614176fe9ea6060516c10fe68e7fd37d0007b713f7650606051010260601d0160a05279d835ebba824c98fb31b83b2ca45c0000000000000000000000006060516e0587f503bb6ea29d25fcb74019645060a0516d04a4fd9f2a8b96949216d2255a6c60605160a05101030260601d01020160c0526d0277594991cfc85f6e2461837cd96060516c240c330e9fb2d9cbaf0fd5aafc606051030260601d0160e0526d1a521255e34f6a5061b25ef1c9c460605160e0510260601d0360e0526db1bbb201f443cf962f1a1d3db4a560605160e0510260601d0160e0526e02c72388d9f74f51a9331fed693f1560605160e0510260601d0360e0526e05180bb14799ab47a8a8cb2a527d5760605160e0510260601d0160e05260e05160c051056101005274029d9dc38563c32e5c2f6dc192ee70ef65f9978af3610100510260805160c30360008112612b29571c8152505b565b600080fd001a108e1a5817021aee1a8900bd1ac184192b3e811000a16576797065728300030a0014
Deployed Bytecode
0x60003560e01c60026007821660011b612b2e01601e39600051565b6354fd4d5081186100995734612b295760208060805260066040527f76322e302e30000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f82600003163682375050601f19601f8251602001011690509050810190506080f35b63c7fab7088118611aee5760a436103417612b29576000610200526110ab56611aee565b634a2ab3be811861105b5760e436103417612b2957610a8c60043510156100e55760006100f0565b631017df8060043511155b15612b29576402540be400602435101561010b576000610119565b66b1a2bc2ec5000060243511155b15612b295767016345785d8a000060a435101561013757600061014c565b6d314dc6448d9338c15b0a0000000060a43511155b15612b295760006104e05260006003905b806105005260c4356105005114610247576105005160028111612b295760051b60440135670de0b6b3a7640000810281670de0b6b3a7640000820418612b2957905060a4358015612b2957808204905090506104e052662386f26fc100006104e05110156101cc5760006101dd565b68056bc75e2d631000006104e05111155b610247576012610520527f556e736166652076616c75657320785b695d00000000000000000000000000006105405261052050610520518061054001601f826000031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b60010181811861015d5750506040366105003760c435610272576001610500526002610520526102a4565b600160c4351861028d576000610500526002610520526102a4565b600260c435186102a4576000610500526001610520525b6004358060ff1c612b2957610540526024358060ff1c612b29576105605260a4358060ff1c612b2957610580526105005160028111612b295760051b604401358060ff1c612b29576105a0526105205160028111612b295760051b604401358060ff1c612b29576105c0526105605161056051026105e0526e0722112107720a4902cd0097b425ed61060052601b61056051671bc16d674ec8000002056e1566336316561edb086701c71c71c7016105c0516127106102d96105e0516105a05161058051610580510205026105405180820281191515600160ff1b8414151782158484840514171615612b2957905090500505058082038281136000831218612b29579050905061062052601b673782dace9d90000061056051016105605102056e1566336316561edb086701c71c71c701612710601b61054051610580516105e051610580516105c0516105a051010380820281191515600160ff1b8414151782158484840514171615612b295790509050050205058082018281126000831218612b29579050905061064052601b61056051670de0b6b3a7640000016fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a90500561066052610600516003026106405180820281191515600160ff1b8414151782158484840514171615612b295790509050610620518015612b2957808205600160ff1b8314156000198314151715612b295790509050610620518082038281136000831218612b2957905090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811315610520578061052f565b806000038114612b2957806000035b90506106805260006106a05273af298d050e4395d69670b12b7f410000000000016106805112156106845772047bf19673df52e37f2410011d10000000000161068051121561066f57701d6329f1c35ca4bfabb9f561000000000161068051121561065b576ec097ce7bc90715b34b9f1000000001610680511215610649576d04ee2d6d415b85acef8100000001610680511215610639576b204fce5e3e2502611000000161068051121561062a5769d3c21bcecceda100000161068051121561061d5768056bc75e2d631000016106805112156106125760016106a052610697565b60646106a052610697565b620f42406106a052610697565b6402540be4006106a052610697565b655af3107a40006106a052610697565b670de0b6b3a76400006106a052610697565b69021e19e0c9bab24000006106a052610697565b6a52b7d2dcc80cd2e40000006106a052610697565b6c0c9f2c9cd04674edea400000006106a0525b60006106c052610620517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156106cf57806106de565b806000038114612b2957806000035b9050610600517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156107125780610721565b806000038114612b2957806000035b9050136107e1576106005161062051057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81131561075f578061076e565b806000038114612b2957806000035b90506106c0526106a051610600516106c0518015612b2957808205600160ff1b8314156000198314151715612b29579050905005610600526106a0516106c051610620510505610620526106a0516106c051610640510505610640526106a0516106c051610660510505610660526108d9565b6106205161060051057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8113156108185780610827565b806000038114612b2957806000035b90506106c0526106a0516106c051610600510205610600526106a051610620516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610620526106a051610640516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610640526106a051610660516106c05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610660525b610600516003026106405180820281191515600160ff1b8414151782158484840514171615612b2957905090506106e052610620516106e05105610620518082038281136000831218612b29579050905061070052610620516106e05160038102816003820518612b29579050056106205160011b8082038281136000831218612b2957905090506106205161062051610600516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a9050601b810281601b820518612b29579050056106605180820281191515600160ff1b8414151782158484840514171615612b295790509050058082038281136000831218612b29579050905061072052610720516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a905061062051610700516fb504f333f9de6484597d89b3754abea081127fffffffffffffffffffffffffffffffff4afb0ccc06219b7ba682764c8ab5416082131615612b29576002810a90508060021b816004820518612b29579050056107005180820281191515600160ff1b8414151782158484840514171615612b2957905090508082018281126000831218612b295790509050610740526000610760526001610740511215610b2d5760406004610120376060604461016037604060a46101c037610b11610780611b81565b610780516107a05260006107c05260406107a061105956610c26565b6107405160008112612b29578060b5710100000000000000000000000000000000008210610b62578160801c91508060401b90505b69010000000000000000008210610b80578160401c91508060201b90505b650100000000008210610b9a578160201c91508060101b90505b63010000008210610bb2578160101c91508060081b90505b620100008201810260121c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c9050808184040160011c905080830480828118828410021890509050905090508060ff1c612b2957610760525b6000610780526000610620511215610cbb57610620517f80000000000000000000000000000000000000000000000000000000000000008114612b295760000360008112612b295760c052610c7c6107a0612525565b6107a0518060ff1c612b29577f80000000000000000000000000000000000000000000000000000000000000008114612b295760000361078052610ce6565b6106205160008112612b295760c052610cd56107a0612525565b6107a0518060ff1c612b2957610780525b60006107a0526001610720511215610d955761072051610760518082038281136000831218612b2957905090507f80000000000000000000000000000000000000000000000000000000000000008114612b295760000360008112612b295760011c60c052610d566107c0612525565b6107c0518060ff1c612b29577f80000000000000000000000000000000000000000000000000000000000000008114612b29576000036107a052610dda565b61072051610760518082018281126000831218612b29579050905060008112612b295760011c60c052610dc96107c0612525565b6107c0518060ff1c612b29576107a0525b670de0b6b3a7640000670de0b6b3a7640000610780516107805180820281191515600160ff1b8414151782158484840514171615612b295790509050056107a05180820281191515600160ff1b8414151782158484840514171615612b295790509050056107c052600361062051610620516107005180820281191515600160ff1b8414151782158484840514171615612b2957905090506107c0518015612b2957808205600160ff1b8314156000198314151715612b2957905090508082018281126000831218612b2957905090506107c0518082038281136000831218612b295790509050056107e052610600516105a0516105c051601b610580516105805180820281191515600160ff1b8414151782158484840514171615612b29579050905005056105805180820281191515600160ff1b8414151782158484840514171615612b295790509050056107e05180820281191515600160ff1b8414151782158484840514171615612b29579050905005610800526108005160008112612b295761082052610600516107e051670de0b6b3a7640000810281670de0b6b3a7640000820518612b295790500560008112612b29576108405260a43561082051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050046104e052662386f26fc0ffff6104e0511015610fd8576000610fe9565b68056bc75e2d631000006104e05111155b611053576012610860527f556e736166652076616c756520666f72207900000000000000000000000000006108805261086050610860518061088001601f826000031636823750506308c379a061082052602061084052601f19601f61086051011660440161083cfd5b60406108205bf35b63bad1dc268118611aee57606436103417612b295760206060600461016037611085610200612732565b610200f3611aee565b637b12e0098118611aee5760c436103417612b295760a435610200525b606060446040376110bd610280611af4565b610280805161022052602081015161024052604081015161026052507901f20fe5212d2319f8671d495c8ba43b5b4b98d506d374fd487a6102205111612b29576102205115612b295761026051610240516102205101016102805260006102a052610200516111595761022051610160526102405161018052610260516101a0526111496102c0612732565b6102c0516003026102a052611303565b6ec097ce7bc90715b34b9f100000000161028051101561127a5769d3c21bcecceda10000016102805110156111f65761020051670de0b6b3a76400006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b2957905060c0526111e96102c0612525565b6102c0516102a052611303565b6102005169d3c21bcecceda10000006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b29579050620f4240810281620f4240820418612b2957905060c05261126d6102c0612525565b6102c0516102a052611303565b610200516ec097ce7bc90715b34b9f10000000006102205161024051808202811583838304141715612b2957905090500461026051808202811583838304141715612b29579050905004601b810281601b820418612b2957905064e8d4a5100081028164e8d4a51000820418612b2957905060c0526112fa6102c0612525565b6102c0516102a0525b610140366102c037600060ff905b80610400526102a0516103a0526102a0516003610260516102a0516003610240516102a051600361022051670de0b6b3a76400000202040202040202046102c052670de0b6b3a7640000602435016102e0526102c0516102e051116113855760016102e0516102c05103016102e052611396565b60016102c0516102e05103016102e0525b6004356127106102e0516024356102e0516024356102a051670de0b6b3a764000002040204020204610300526102e0516102c0516753444835ec580000020461032052670de0b6b3a76400006102a0516103205102046102c0516003610300510204670de0b6b3a7640000610320516102805102046102805101010361034052610340516102a051610280516103405101808202811583838304141715612b2957905090500461036052610340516102a0516102a051808202811583838304141715612b2957905090500461038052670de0b6b3a763ffff6102c05111156114d257610380516102c051670de0b6b3a76400006102c05103670de0b6b3a76400006102a051610340516103005104808202811583838304141715612b295790509050040204808203828111612b29579050905061038052611528565b610380516102c0516102c051670de0b6b3a764000003670de0b6b3a76400006102a051610340516103005104808202811583838304141715612b295790509050040204808201828110612b295790509050610380525b61038051610360511161154a5761036051610380510360011c6102a052611558565b6103805161036051036102a0525b6103a0516102a05111611577576102a0516103a051036103c052611585565b6103a0516102a051036103c0525b6102a05180662386f26fc10000811882662386f26fc100001102189050655af3107a40006103c05102101561168a5760006003905b8060051b6102200151610420526102a051670de0b6b3a76400006104205102046103e052662386f26fc0ffff6103e05110156115f7576000611608565b68056bc75e2d631000006103e05111155b611672576012610440527f556e736166652076616c75657320785b695d00000000000000000000000000006104605261044050610440518061046001601f826000031636823750506308c379a061040052602061042052601f19601f61044051011660440161041cfd5b6001018181186115ba575050505060206102a06116fc565b6001018181186113115750506010610400527f446964206e6f7420636f6e7665726765000000000000000000000000000000006104205261040050610400518061042001601f826000031636823750506308c379a06103c05260206103e052601f19601f6104005101166044016103dcfd5bf3611aee565b63754b76b38118611aee5760c436103417612b295767016345785d8a00006064351015611730576000611745565b6d314dc6448d9338c15b0a0000000060643511155b15612b2957606435606435606435600435601b810281601b820418612b29579050602435808202811583838304141715612b29579050905004604435808202811583838304141715612b295790509050046ec097ce7bc90715b34b9f10000000008102816ec097ce7bc90715b34b9f1000000000820418612b29579050046040526ec097ce7bc90715b34b9f10000000006ec097ce7bc90715b34b9f10000000006040518060011b818160011c18612b29579050604051808202811583838304141715612b29579050905004604051808202811583838304141715612b295790509050046002670de0b6b3a764000060a435010a808201828110612b295790509050670de0b6b3a76400006ec097ce7bc90715b34b9f100000000060026040510a046729a2241af62c000060a43560011b01808202811583838304141715612b29579050905004808203828111612b295790509050606052612710600260a4350a60843502046080526060516ec097ce7bc90715b34b9f1000000000606435608051600435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b29579050905060a05260a0516004356060516ec097ce7bc90715b34b9f1000000000606435608051602435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b295790509050808202811583838304141715612b2957905090506024358015612b295780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790500460c05260a0516004356060516ec097ce7bc90715b34b9f1000000000606435608051604435808202811583838304141715612b29579050905004604051808202811583838304141715612b29579050905004808201828110612b295790509050808202811583838304141715612b2957905090506044358015612b295780820490509050670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790500460e052604060c0f3611aee565b63f42c56c28118611aee57602436103417612b2957602060043560c052611a80610160612525565b610160f3611aee565b63fa18042d8118611aee57608436103417612b295760206060600460403760643560a052611ab86101006127ac565b610100f3611aee565b6381d18d878118611aee57602436103417612b29576020600435604052611ae96101206128d4565b610120f35b60006000fd5b60405160a05260605160c05260805160e05260a0516101005260c05160a0511015611b275760c05160a0526101005160c0525b60e05160a0511015611b485760a0516101005260e05160a0526101005160e0525b60e05160c0511015611b695760c0516101005260e05160c0526101005160e0525b60a051815260c051602082015260e051604082015250565b60006102005260006003905b80610220526101e0516102205114611c7a576102205160028111612b295760051b6101600151670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790506101c0518015612b29578082049050905061020052662386f26fc10000610200511015611bff576000611c10565b68056bc75e2d631000006102005111155b611c7a576012610240527f556e736166652076616c75657320785b695d00000000000000000000000000006102605261024050610240518061026001601f826000031636823750506308c379a061020052602061022052601f19601f61024051011660440161021cfd5b600101818118611b8d5750506101c05160038104905061022052670de0b6b3a7640000610240526000610260526101605161028052610180516102a0526101a0516102c05260006101e05160028111612b295760051b6102800152610280516040526102a0516060526102c051608052611cf56102e0611af4565b6102e0805161034052602081015161036052604081015161038052506103405161028052610360516102a052610380516102c05261028051655af3107a4000810490506101c051655af3107a40008104905080828118828411021890509050606481811860648311021890506102e052600260028101905b8061030052610300518060030360038111612b2957905060028111612b295760051b610280015161032052610220516101c051808202811583838304141715612b2957905090506103205160038102816003820418612b295790508015612b295780820490509050610220526102605161032051808201828110612b29579050905061026052600101818118611d6d57505060006002905b8061030052610240516103005160028111612b295760051b6102800151808202811583838304141715612b29579050905060038102816003820418612b295790506101c0518015612b29578082049050905061024052600101818118611e055750506101803661030037600060ff905b806104805261022051610320526102405161022051808202811583838304141715612b29579050905060038102816003820418612b295790506101c0518015612b295780820490509050610340526102605161022051808201828110612b2957905090506103605261014051670de0b6b3a76400008101818110612b2957905061038052610340516103805111611f32576103405161038051808203828111612b29579050905060018101818110612b2957905061038052611f5a565b6103805161034051808203828111612b29579050905060018101818110612b29579050610380525b6101c051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610140518015612b29578082049050905061038051808202811583838304141715612b295790509050610140518015612b29578082049050905061038051808202811583838304141715612b295790509050612710810281612710820418612b29579050610120518015612b2957808204905090506103a05261034051671bc16d674ec80000810281671bc16d674ec80000820418612b29579050610380518015612b29578082049050905080670de0b6b3a764000001670de0b6b3a76400008110612b295790506103c05261022051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610360516103c051808202811583838304141715612b295790509050808201828110612b2957905090506103a051808201828110612b2957905090506103e0526101c0516103c051808202811583838304141715612b29579050905061040052610400516103e051106120f6576103e05161040051808203828111612b2957905090506103e052612109565b610320518060011c905061022052612393565b6103e051610220518015612b295780820490509050610420526103a051610420518015612b295780820490509050610440526103e0516101c051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050808201828110612b295790509050610420518015612b29578082049050905061044051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610340518015612b295780820490509050808201828110612b295790509050610460526104405161036051670de0b6b3a7640000810281670de0b6b3a7640000820418612b29579050610420518015612b295780820490509050808201828110612b2957905090506104405261044051610460511061223a576104605161044051808203828111612b29579050905061022052612249565b610320518060011c9050610220525b610320516102205111612275576103205161022051808203828111612b29579050905061030052612290565b6102205161032051808203828111612b295790509050610300525b6102e05161022051655af3107a400081049050808281188284110218905090506103005110156123935761022051670de0b6b3a7640000810281670de0b6b3a7640000820418612b295790506101c0518015612b29578082049050905061020052662386f26fc1000061020051101561230a57600061231b565b68056bc75e2d631000006102005111155b6123855760126104a0527f556e736166652076616c756520666f72207900000000000000000000000000006104c0526104a0506104a051806104c001601f826000031636823750506308c379a061046052602061048052601f19601f6104a051011660440161047cfd5b610220518352505050612405565b600101818118611e755750506010610480527f446964206e6f7420636f6e7665726765000000000000000000000000000000006104a0526104805061048051806104a001601f826000031636823750506308c379a061044052602061046052601f19601f61048051011660440161045cfd5b565b604051608052600060a05260405160801c1561242c5760405160801c608052608060a0525b60805160401c1561244a5760805160401c608052604060a0510160a0525b60805160201c156124685760805160201c608052602060a0510160a0525b60805160101c156124865760805160101c608052601060a0510160a0525b60805160081c156124a45760805160081c608052600860a0510160a0525b60805160041c156124c25760805160041c608052600460a0510160a0525b60805160021c156124e05760805160021c608052600260a0510160a0525b60805160011c156124f557600160a0510160a0525b60605161250357600061250e565b604051600160a0511b105b1561251d57600160a0510160a0525b60a051815250565b600060e0527812725dd1d243aba0e75fe645cc4873f9e64d542c5db234000060c051101561259a57710154484932d2e725a5bbca17a3aba173d3d560c0511015612585576ec097ce7bc90715b34b9f100000000060c0510260e0526125a1565b670de0b6b3a764000060c0510260e0526125a1565b60c05160e0525b60e05160405260006060526125b7610120612407565b610120518060ff1c612b2957610100526101005160008112612b295760038106905061012052610120516103e80a610120516104ec0a60036101005160008112612b29570460020a020461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b010461014052600361014051610140510260e051046101405160011b0104610140527812725dd1d243aba0e75fe645cc4873f9e64d542c5db234000060c051101561271957710154484932d2e725a5bbca17a3aba173d3d560c0511061272957620f4240610140510261014052612729565b64e8d4a510006101405102610140525b61014051815250565b670de0b6b3a7640000670de0b6b3a76400006101605161018051808202811583838304141715612b295790509050046101a051808202811583838304141715612b295790509050046101c0526101c0516127905760008152506127aa565b6101c05160c0526127a26101e0612525565b6101e0518152505b565b604051606051808201828110612b295790509050608051808201828110612b29579050905060c0526040516729a2241af62c00008102816729a2241af62c0000820418612b2957905060c0518015612b29578082049050905060e05260c05160e05160038102816003820418612b29579050606051808202811583838304141715612b2957905090500460e05260c05160e05160038102816003820418612b29579050608051808202811583838304141715612b2957905090500460e05260a051156128cc5760a051670de0b6b3a7640000810281670de0b6b3a7640000820418612b2957905060a051670de0b6b3a76400008101818110612b2957905060e051808203828111612b2957905090508015612b29578082049050905060e0525b60e051815250565b6040516060527ffffffffffffffffffffffffffffffffffffffffffffffffdb731c958f34d94c16040511361290d576000815250612b27565b680755bf798b4a1bf1e4604051131561297d5760106080527f7761645f657870206f766572666c6f770000000000000000000000000000000060a0526080506080518060a001601f826000031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6503782dace9d9604051604e1b056060526b8000000000000000000000006bb17217f7d1cf79abc9e3b39860605160601b050160601d6080526bb17217f7d1cf79abc9e3b39860805102606051036060526d02d16720577bd19bf614176fe9ea6060516c10fe68e7fd37d0007b713f7650606051010260601d0160a05279d835ebba824c98fb31b83b2ca45c0000000000000000000000006060516e0587f503bb6ea29d25fcb74019645060a0516d04a4fd9f2a8b96949216d2255a6c60605160a05101030260601d01020160c0526d0277594991cfc85f6e2461837cd96060516c240c330e9fb2d9cbaf0fd5aafc606051030260601d0160e0526d1a521255e34f6a5061b25ef1c9c460605160e0510260601d0360e0526db1bbb201f443cf962f1a1d3db4a560605160e0510260601d0160e0526e02c72388d9f74f51a9331fed693f1560605160e0510260601d0360e0526e05180bb14799ab47a8a8cb2a527d5760605160e0510260601d0160e05260e05160c051056101005274029d9dc38563c32e5c2f6dc192ee70ef65f9978af3610100510260805160c30360008112612b29571c8152505b565b600080fd001a108e1a5817021aee1a8900bd1ac1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.