Contract
0x0fa949783947bf6c1b171db13aeacbb488845b3f
3
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 1 internal transaction
Parent Txn Hash | Block | From | To | Value | |||
---|---|---|---|---|---|---|---|
0x23c83ccde27da5dde8263932c271bb8373abcd98cdcce8221348627671a379ef | 19420477 | 525 days 11 hrs ago | 0x7eeac6cddbd1d0b8af061742d41877d7f707289a | Contract Creation | 0 FTM |
[ Download CSV Export ]
Contract Source Code Verified (Exact Match)
Contract Name:
Vyper_contract
Compiler Version
vyper:0.2.16
Contract Source Code (Vyper language format)
# @version 0.2.16 """ @title Curve gPool for use on Fantom @author Curve.Fi @license Copyright (c) Curve.Fi, 2020 - all rights reserved @notice Pool implementation with aToken-style lending """ from vyper.interfaces import ERC20 interface LendingPool: def withdraw(_underlying_asset: address, _amount: uint256, _receiver: address): nonpayable interface CurveToken: def mint(_to: address, _value: uint256) -> bool: nonpayable def burnFrom(_to: address, _value: uint256) -> bool: nonpayable interface GeistStaking: def exit(): nonpayable # Events event TokenExchange: buyer: indexed(address) sold_id: int128 tokens_sold: uint256 bought_id: int128 tokens_bought: uint256 event TokenExchangeUnderlying: buyer: indexed(address) sold_id: int128 tokens_sold: uint256 bought_id: int128 tokens_bought: uint256 event AddLiquidity: provider: indexed(address) token_amounts: uint256[N_COINS] fees: uint256[N_COINS] invariant: uint256 token_supply: uint256 event RemoveLiquidity: provider: indexed(address) token_amounts: uint256[N_COINS] fees: uint256[N_COINS] token_supply: uint256 event RemoveLiquidityOne: provider: indexed(address) token_amount: uint256 coin_amount: uint256 event RemoveLiquidityImbalance: provider: indexed(address) token_amounts: uint256[N_COINS] fees: uint256[N_COINS] invariant: uint256 token_supply: uint256 event CommitNewAdmin: deadline: indexed(uint256) admin: indexed(address) event NewAdmin: admin: indexed(address) event CommitNewFee: deadline: indexed(uint256) fee: uint256 admin_fee: uint256 offpeg_fee_multiplier: uint256 event NewFee: fee: uint256 admin_fee: uint256 offpeg_fee_multiplier: uint256 event RampA: old_A: uint256 new_A: uint256 initial_time: uint256 future_time: uint256 event StopRampA: A: uint256 t: uint256 N_COINS: constant(int128) = 3 PRECISION_MUL: constant(uint256[N_COINS]) = [1, 1000000000000, 1000000000000] PRECISION: constant(uint256) = 10 ** 18 FEE_DENOMINATOR: constant(uint256) = 10 ** 10 MAX_ADMIN_FEE: constant(uint256) = 10 * 10 ** 9 MAX_FEE: constant(uint256) = 5 * 10 ** 9 MAX_A: constant(uint256) = 10 ** 6 MAX_A_CHANGE: constant(uint256) = 10 A_PRECISION: constant(uint256) = 100 ADMIN_ACTIONS_DELAY: constant(uint256) = 3 * 86400 MIN_RAMP_TIME: constant(uint256) = 86400 GEIST_REWARDS: constant(address) = 0x297FddC5c33Ef988dd03bd13e162aE084ea1fE57 GEIST_STAKING: constant(address) = 0x49c93a95dbcc9A6A4D8f77E59c038ce5020e82f8 GEIST_TOKEN: constant(address) = 0xd8321AA83Fb0a4ECd6348D4577431310A6E0814d LENDING_POOL: constant(address) = 0x9FAD24f572045c7869117160A571B2e50b10d068 coins: public(address[N_COINS]) underlying_coins: public(address[N_COINS]) admin_balances: public(uint256[N_COINS]) fee: public(uint256) # fee * 1e10 offpeg_fee_multiplier: public(uint256) # * 1e10 admin_fee: public(uint256) # admin_fee * 1e10 owner: public(address) lp_token: public(address) aave_referral: uint256 initial_A: public(uint256) future_A: public(uint256) initial_A_time: public(uint256) future_A_time: public(uint256) admin_actions_deadline: public(uint256) transfer_ownership_deadline: public(uint256) future_fee: public(uint256) future_admin_fee: public(uint256) future_offpeg_fee_multiplier: public(uint256) # * 1e10 future_owner: public(address) is_killed: bool kill_deadline: uint256 KILL_DEADLINE_DT: constant(uint256) = 2 * 30 * 86400 reward_receiver: public(address) admin_fee_receiver: public(address) @external def __init__( _coins: address[N_COINS], _underlying_coins: address[N_COINS], _pool_token: address, _A: uint256, _fee: uint256, _admin_fee: uint256, _offpeg_fee_multiplier: uint256, ): """ @notice Contract constructor @param _coins List of wrapped coin addresses @param _underlying_coins List of underlying coin addresses @param _pool_token Pool LP token address @param _A Amplification coefficient multiplied by n * (n - 1) @param _fee Swap fee expressed as an integer with 1e10 precision @param _admin_fee Percentage of fee taken as an admin fee, expressed as an integer with 1e10 precision @param _offpeg_fee_multiplier Offpeg fee multiplier """ for i in range(N_COINS): assert _coins[i] != ZERO_ADDRESS assert _underlying_coins[i] != ZERO_ADDRESS self.coins = _coins self.underlying_coins = _underlying_coins self.initial_A = _A * A_PRECISION self.future_A = _A * A_PRECISION self.fee = _fee self.admin_fee = _admin_fee self.offpeg_fee_multiplier = _offpeg_fee_multiplier self.owner = msg.sender self.admin_fee_receiver = msg.sender self.kill_deadline = block.timestamp + KILL_DEADLINE_DT self.lp_token = _pool_token # approve transfer of underlying coin to aave lending pool for coin in _underlying_coins: _response: Bytes[32] = raw_call( coin, concat( method_id("approve(address,uint256)"), convert(LENDING_POOL, bytes32), convert(MAX_UINT256, bytes32) ), max_outsize=32 ) if len(_response) != 0: assert convert(_response, bool) @view @internal def _A() -> uint256: t1: uint256 = self.future_A_time A1: uint256 = self.future_A if block.timestamp < t1: # handle ramping up and down of A A0: uint256 = self.initial_A t0: uint256 = self.initial_A_time # Expressions in uint256 cannot have negative numbers, thus "if" if A1 > A0: return A0 + (A1 - A0) * (block.timestamp - t0) / (t1 - t0) else: return A0 - (A0 - A1) * (block.timestamp - t0) / (t1 - t0) else: # when t1 == 0 or block.timestamp >= t1 return A1 @view @external def A() -> uint256: return self._A() / A_PRECISION @view @external def A_precise() -> uint256: return self._A() @pure @internal def _dynamic_fee(xpi: uint256, xpj: uint256, _fee: uint256, _feemul: uint256) -> uint256: if _feemul <= FEE_DENOMINATOR: return _fee else: xps2: uint256 = (xpi + xpj) xps2 *= xps2 # Doing just ** 2 can overflow apparently return (_feemul * _fee) / ( (_feemul - FEE_DENOMINATOR) * 4 * xpi * xpj / xps2 + \ FEE_DENOMINATOR) @view @external def dynamic_fee(i: int128, j: int128) -> uint256: """ @notice Return the fee for swapping between `i` and `j` @param i Index value for the coin to send @param j Index value of the coin to recieve @return Swap fee expressed as an integer with 1e10 precision """ precisions: uint256[N_COINS] = PRECISION_MUL xpi: uint256 = (ERC20(self.coins[i]).balanceOf(self) - self.admin_balances[i]) * precisions[i] xpj: uint256 = (ERC20(self.coins[j]).balanceOf(self) - self.admin_balances[j]) * precisions[j] return self._dynamic_fee(xpi, xpj, self.fee, self.offpeg_fee_multiplier) @view @external def balances(i: uint256) -> uint256: """ @notice Get the current balance of a coin within the pool, less the accrued admin fees @param i Index value for the coin to query balance of @return Token balance """ return ERC20(self.coins[i]).balanceOf(self) - self.admin_balances[i] @view @internal def _balances() -> uint256[N_COINS]: result: uint256[N_COINS] = empty(uint256[N_COINS]) for i in range(N_COINS): result[i] = ERC20(self.coins[i]).balanceOf(self) - self.admin_balances[i] return result @pure @internal def get_D(xp: uint256[N_COINS], amp: uint256) -> uint256: """ D invariant calculation in non-overflowing integer operations iteratively A * sum(x_i) * n**n + D = A * D * n**n + D**(n+1) / (n**n * prod(x_i)) Converging solution: D[j+1] = (A * n**n * sum(x_i) - D[j]**(n+1) / (n**n prod(x_i))) / (A * n**n - 1) """ S: uint256 = 0 for _x in xp: S += _x if S == 0: return 0 Dprev: uint256 = 0 D: uint256 = S Ann: uint256 = amp * N_COINS for _i in range(255): D_P: uint256 = D for _x in xp: D_P = D_P * D / (_x * N_COINS + 1) # +1 is to prevent /0 Dprev = D D = (Ann * S / A_PRECISION + D_P * N_COINS) * D / ((Ann - A_PRECISION) * D / A_PRECISION + (N_COINS + 1) * D_P) # Equality with the precision of 1 if D > Dprev: if D - Dprev <= 1: return D else: if Dprev - D <= 1: return D # convergence typically occurs in 4 rounds or less, this should be unreachable! # if it does happen the pool is borked and LPs can withdraw via `remove_liquidity` raise @view @internal def get_D_precisions(coin_balances: uint256[N_COINS], amp: uint256) -> uint256: xp: uint256[N_COINS] = PRECISION_MUL for i in range(N_COINS): xp[i] *= coin_balances[i] return self.get_D(xp, amp) @view @external def get_virtual_price() -> uint256: """ @notice The current virtual price of the pool LP token @dev Useful for calculating profits @return LP token virtual price normalized to 1e18 """ D: uint256 = self.get_D_precisions(self._balances(), self._A()) # D is in the units similar to DAI (e.g. converted to precision 1e18) # When balanced, D = n * x_u - total virtual value of the portfolio token_supply: uint256 = ERC20(self.lp_token).totalSupply() return D * PRECISION / token_supply @view @external def calc_token_amount(_amounts: uint256[N_COINS], is_deposit: bool) -> uint256: """ @notice Calculate addition or reduction in token supply from a deposit or withdrawal @dev This calculation accounts for slippage, but not fees. Needed to prevent front-running, not for precise calculations! @param _amounts Amount of each coin being deposited @param is_deposit set True for deposits, False for withdrawals @return Expected amount of LP tokens received """ coin_balances: uint256[N_COINS] = self._balances() amp: uint256 = self._A() D0: uint256 = self.get_D_precisions(coin_balances, amp) for i in range(N_COINS): if is_deposit: coin_balances[i] += _amounts[i] else: coin_balances[i] -= _amounts[i] D1: uint256 = self.get_D_precisions(coin_balances, amp) token_amount: uint256 = ERC20(self.lp_token).totalSupply() diff: uint256 = 0 if is_deposit: diff = D1 - D0 else: diff = D0 - D1 return diff * token_amount / D0 @external def claim_rewards(): # push wAvax rewards into the reward receiver reward_receiver: address = self.reward_receiver if reward_receiver != ZERO_ADDRESS: raw_call( GEIST_REWARDS, concat( method_id("claim(address,address[])"), convert(self, bytes32), convert(32 * 2, bytes32), convert(3, bytes32), convert(self.coins[0], bytes32), convert(self.coins[1], bytes32), convert(self.coins[2], bytes32), ) ) GeistStaking(GEIST_STAKING).exit() amount: uint256 = ERC20(GEIST_TOKEN).balanceOf(self) if amount > 0: assert ERC20(GEIST_TOKEN).transfer(reward_receiver, amount) @external @nonreentrant('lock') def add_liquidity(_amounts: uint256[N_COINS], _min_mint_amount: uint256, _use_underlying: bool = False) -> uint256: """ @notice Deposit coins into the pool @param _amounts List of amounts of coins to deposit @param _min_mint_amount Minimum amount of LP tokens to mint from the deposit @param _use_underlying If True, deposit underlying assets instead of aTokens @return Amount of LP tokens received by depositing """ assert not self.is_killed # dev: is killed # Initial invariant amp: uint256 = self._A() old_balances: uint256[N_COINS] = self._balances() lp_token: address = self.lp_token token_supply: uint256 = ERC20(lp_token).totalSupply() D0: uint256 = 0 if token_supply != 0: D0 = self.get_D_precisions(old_balances, amp) new_balances: uint256[N_COINS] = old_balances for i in range(N_COINS): if token_supply == 0: assert _amounts[i] != 0 # dev: initial deposit requires all coins new_balances[i] += _amounts[i] # Invariant after change D1: uint256 = self.get_D_precisions(new_balances, amp) assert D1 > D0 # We need to recalculate the invariant accounting for fees # to calculate fair user's share fees: uint256[N_COINS] = empty(uint256[N_COINS]) mint_amount: uint256 = 0 if token_supply != 0: # Only account for fees if we are not the first to deposit ys: uint256 = (D0 + D1) / N_COINS _fee: uint256 = self.fee * N_COINS / (4 * (N_COINS - 1)) _feemul: uint256 = self.offpeg_fee_multiplier _admin_fee: uint256 = self.admin_fee difference: uint256 = 0 for i in range(N_COINS): ideal_balance: uint256 = D1 * old_balances[i] / D0 new_balance: uint256 = new_balances[i] if ideal_balance > new_balance: difference = ideal_balance - new_balance else: difference = new_balance - ideal_balance xs: uint256 = old_balances[i] + new_balance fees[i] = self._dynamic_fee(xs, ys, _fee, _feemul) * difference / FEE_DENOMINATOR if _admin_fee != 0: self.admin_balances[i] += fees[i] * _admin_fee / FEE_DENOMINATOR new_balances[i] = new_balance - fees[i] D2: uint256 = self.get_D_precisions(new_balances, amp) mint_amount = token_supply * (D2 - D0) / D0 else: mint_amount = D1 # Take the dust if there was any assert mint_amount >= _min_mint_amount, "Slippage screwed you" # Take coins from the sender if _use_underlying: aave_referral: bytes32 = convert(self.aave_referral, bytes32) # Take coins from the sender for i in range(N_COINS): amount: uint256 = _amounts[i] if amount != 0: coin: address = self.underlying_coins[i] # transfer underlying coin from msg.sender to self _response: Bytes[32] = raw_call( coin, concat( method_id("transferFrom(address,address,uint256)"), convert(msg.sender, bytes32), convert(self, bytes32), convert(amount, bytes32) ), max_outsize=32 ) if len(_response) != 0: assert convert(_response, bool) # deposit to aave lending pool raw_call( LENDING_POOL, concat( method_id("deposit(address,uint256,address,uint16)"), convert(coin, bytes32), convert(amount, bytes32), convert(self, bytes32), aave_referral, ) ) else: for i in range(N_COINS): amount: uint256 = _amounts[i] if amount != 0: assert ERC20(self.coins[i]).transferFrom(msg.sender, self, amount) # dev: failed transfer # Mint pool tokens CurveToken(lp_token).mint(msg.sender, mint_amount) log AddLiquidity(msg.sender, _amounts, fees, D1, token_supply + mint_amount) return mint_amount @view @internal def get_y(i: int128, j: int128, x: uint256, xp: uint256[N_COINS]) -> uint256: """ Calculate x[j] if one makes x[i] = x Done by solving quadratic equation iteratively. x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A) x_1**2 + b*x_1 = c x_1 = (x_1**2 + c) / (2*x_1 + b) """ # x in the input is converted to the same price/precision assert i != j # dev: same coin assert j >= 0 # dev: j below zero assert j < N_COINS # dev: j above N_COINS # should be unreachable, but good for safety assert i >= 0 assert i < N_COINS amp: uint256 = self._A() D: uint256 = self.get_D(xp, amp) Ann: uint256 = amp * N_COINS c: uint256 = D S_: uint256 = 0 _x: uint256 = 0 y_prev: uint256 = 0 for _i in range(N_COINS): if _i == i: _x = x elif _i != j: _x = xp[_i] else: continue S_ += _x c = c * D / (_x * N_COINS) c = c * D * A_PRECISION / (Ann * N_COINS) b: uint256 = S_ + D * A_PRECISION / Ann # - D y: uint256 = D for _i in range(255): y_prev = y y = (y*y + c) / (2 * y + b - D) # Equality with the precision of 1 if y > y_prev: if y - y_prev <= 1: return y else: if y_prev - y <= 1: return y raise @view @internal def _get_dy(i: int128, j: int128, dx: uint256) -> uint256: xp: uint256[N_COINS] = self._balances() precisions: uint256[N_COINS] = PRECISION_MUL for k in range(N_COINS): xp[k] *= precisions[k] x: uint256 = xp[i] + dx * precisions[i] y: uint256 = self.get_y(i, j, x, xp) dy: uint256 = (xp[j] - y) / precisions[j] _fee: uint256 = self._dynamic_fee( (xp[i] + x) / 2, (xp[j] + y) / 2, self.fee, self.offpeg_fee_multiplier ) * dy / FEE_DENOMINATOR return dy - _fee @view @external def get_dy(i: int128, j: int128, dx: uint256) -> uint256: return self._get_dy(i, j, dx) @view @external def get_dy_underlying(i: int128, j: int128, dx: uint256) -> uint256: return self._get_dy(i, j, dx) @internal def _exchange(i: int128, j: int128, dx: uint256) -> uint256: assert not self.is_killed # dev: is killed # dx and dy are in aTokens xp: uint256[N_COINS] = self._balances() precisions: uint256[N_COINS] = PRECISION_MUL for k in range(N_COINS): xp[k] *= precisions[k] x: uint256 = xp[i] + dx * precisions[i] y: uint256 = self.get_y(i, j, x, xp) dy: uint256 = xp[j] - y dy_fee: uint256 = dy * self._dynamic_fee( (xp[i] + x) / 2, (xp[j] + y) / 2, self.fee, self.offpeg_fee_multiplier ) / FEE_DENOMINATOR admin_fee: uint256 = self.admin_fee if admin_fee != 0: dy_admin_fee: uint256 = dy_fee * admin_fee / FEE_DENOMINATOR if dy_admin_fee != 0: self.admin_balances[j] += dy_admin_fee / precisions[j] return (dy - dy_fee) / precisions[j] @external @nonreentrant('lock') def exchange(i: int128, j: int128, dx: uint256, min_dy: uint256) -> uint256: """ @notice Perform an exchange between two coins @dev Index values can be found via the `coins` public getter method @param i Index value for the coin to send @param j Index valie of the coin to recieve @param dx Amount of `i` being exchanged @param min_dy Minimum amount of `j` to receive @return Actual amount of `j` received """ dy: uint256 = self._exchange(i, j, dx) assert dy >= min_dy, "Exchange resulted in fewer coins than expected" assert ERC20(self.coins[i]).transferFrom(msg.sender, self, dx) assert ERC20(self.coins[j]).transfer(msg.sender, dy) log TokenExchange(msg.sender, i, dx, j, dy) return dy @external @nonreentrant('lock') def exchange_underlying(i: int128, j: int128, dx: uint256, min_dy: uint256) -> uint256: """ @notice Perform an exchange between two underlying coins @dev Index values can be found via the `underlying_coins` public getter method @param i Index value for the underlying coin to send @param j Index valie of the underlying coin to recieve @param dx Amount of `i` being exchanged @param min_dy Minimum amount of `j` to receive @return Actual amount of `j` received """ dy: uint256 = self._exchange(i, j, dx) assert dy >= min_dy, "Exchange resulted in fewer coins than expected" u_coin_i: address = self.underlying_coins[i] # transfer underlying coin from msg.sender to self _response: Bytes[32] = raw_call( u_coin_i, concat( method_id("transferFrom(address,address,uint256)"), convert(msg.sender, bytes32), convert(self, bytes32), convert(dx, bytes32) ), max_outsize=32 ) if len(_response) != 0: assert convert(_response, bool) # deposit to aave lending pool raw_call( LENDING_POOL, concat( method_id("deposit(address,uint256,address,uint16)"), convert(u_coin_i, bytes32), convert(dx, bytes32), convert(self, bytes32), convert(self.aave_referral, bytes32), ) ) # withdraw `j` underlying from lending pool and transfer to caller LendingPool(LENDING_POOL).withdraw(self.underlying_coins[j], dy, msg.sender) log TokenExchangeUnderlying(msg.sender, i, dx, j, dy) return dy @external @nonreentrant('lock') def remove_liquidity( _amount: uint256, _min_amounts: uint256[N_COINS], _use_underlying: bool = False, ) -> uint256[N_COINS]: """ @notice Withdraw coins from the pool @dev Withdrawal amounts are based on current deposit ratios @param _amount Quantity of LP tokens to burn in the withdrawal @param _min_amounts Minimum amounts of underlying coins to receive @param _use_underlying If True, withdraw underlying assets instead of aTokens @return List of amounts of coins that were withdrawn """ amounts: uint256[N_COINS] = self._balances() lp_token: address = self.lp_token total_supply: uint256 = ERC20(lp_token).totalSupply() CurveToken(lp_token).burnFrom(msg.sender, _amount) # dev: insufficient funds for i in range(N_COINS): value: uint256 = amounts[i] * _amount / total_supply assert value >= _min_amounts[i], "Withdrawal resulted in fewer coins than expected" amounts[i] = value if _use_underlying: LendingPool(LENDING_POOL).withdraw(self.underlying_coins[i], value, msg.sender) else: assert ERC20(self.coins[i]).transfer(msg.sender, value) log RemoveLiquidity(msg.sender, amounts, empty(uint256[N_COINS]), total_supply - _amount) return amounts @external @nonreentrant('lock') def remove_liquidity_imbalance( _amounts: uint256[N_COINS], _max_burn_amount: uint256, _use_underlying: bool = False ) -> uint256: """ @notice Withdraw coins from the pool in an imbalanced amount @param _amounts List of amounts of underlying coins to withdraw @param _max_burn_amount Maximum amount of LP token to burn in the withdrawal @param _use_underlying If True, withdraw underlying assets instead of aTokens @return Actual amount of the LP token burned in the withdrawal """ assert not self.is_killed # dev: is killed amp: uint256 = self._A() old_balances: uint256[N_COINS] = self._balances() D0: uint256 = self.get_D_precisions(old_balances, amp) new_balances: uint256[N_COINS] = old_balances for i in range(N_COINS): new_balances[i] -= _amounts[i] D1: uint256 = self.get_D_precisions(new_balances, amp) ys: uint256 = (D0 + D1) / N_COINS lp_token: address = self.lp_token token_supply: uint256 = ERC20(lp_token).totalSupply() assert token_supply != 0 # dev: zero total supply _fee: uint256 = self.fee * N_COINS / (4 * (N_COINS - 1)) _feemul: uint256 = self.offpeg_fee_multiplier _admin_fee: uint256 = self.admin_fee fees: uint256[N_COINS] = empty(uint256[N_COINS]) for i in range(N_COINS): ideal_balance: uint256 = D1 * old_balances[i] / D0 new_balance: uint256 = new_balances[i] difference: uint256 = 0 if ideal_balance > new_balance: difference = ideal_balance - new_balance else: difference = new_balance - ideal_balance xs: uint256 = new_balance + old_balances[i] fees[i] = self._dynamic_fee(xs, ys, _fee, _feemul) * difference / FEE_DENOMINATOR if _admin_fee != 0: self.admin_balances[i] += fees[i] * _admin_fee / FEE_DENOMINATOR new_balances[i] -= fees[i] D2: uint256 = self.get_D_precisions(new_balances, amp) token_amount: uint256 = (D0 - D2) * token_supply / D0 assert token_amount != 0 # dev: zero tokens burned assert token_amount <= _max_burn_amount, "Slippage screwed you" CurveToken(lp_token).burnFrom(msg.sender, token_amount) # dev: insufficient funds for i in range(N_COINS): amount: uint256 = _amounts[i] if amount != 0: if _use_underlying: LendingPool(LENDING_POOL).withdraw(self.underlying_coins[i], amount, msg.sender) else: assert ERC20(self.coins[i]).transfer(msg.sender, amount) log RemoveLiquidityImbalance(msg.sender, _amounts, fees, D1, token_supply - token_amount) return token_amount @pure @internal def get_y_D(A_: uint256, i: int128, xp: uint256[N_COINS], D: uint256) -> uint256: """ Calculate x[i] if one reduces D from being calculated for xp to D Done by solving quadratic equation iteratively. x_1**2 + x1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A) x_1**2 + b*x_1 = c x_1 = (x_1**2 + c) / (2*x_1 + b) """ # x in the input is converted to the same price/precision assert i >= 0 # dev: i below zero assert i < N_COINS # dev: i above N_COINS Ann: uint256 = A_ * N_COINS c: uint256 = D S_: uint256 = 0 _x: uint256 = 0 y_prev: uint256 = 0 for _i in range(N_COINS): if _i != i: _x = xp[_i] else: continue S_ += _x c = c * D / (_x * N_COINS) c = c * D * A_PRECISION / (Ann * N_COINS) b: uint256 = S_ + D * A_PRECISION / Ann y: uint256 = D for _i in range(255): y_prev = y y = (y*y + c) / (2 * y + b - D) # Equality with the precision of 1 if y > y_prev: if y - y_prev <= 1: return y else: if y_prev - y <= 1: return y raise @view @internal def _calc_withdraw_one_coin(_token_amount: uint256, i: int128) -> uint256: # First, need to calculate # * Get current D # * Solve Eqn against y_i for D - _token_amount amp: uint256 = self._A() xp: uint256[N_COINS] = self._balances() precisions: uint256[N_COINS] = PRECISION_MUL for j in range(N_COINS): xp[j] *= precisions[j] D0: uint256 = self.get_D(xp, amp) D1: uint256 = D0 - _token_amount * D0 / ERC20(self.lp_token).totalSupply() new_y: uint256 = self.get_y_D(amp, i, xp, D1) xp_reduced: uint256[N_COINS] = xp ys: uint256 = (D0 + D1) / (2 * N_COINS) _fee: uint256 = self.fee * N_COINS / (4 * (N_COINS - 1)) feemul: uint256 = self.offpeg_fee_multiplier for j in range(N_COINS): dx_expected: uint256 = 0 xavg: uint256 = 0 if j == i: dx_expected = xp[j] * D1 / D0 - new_y xavg = (xp[j] + new_y) / 2 else: dx_expected = xp[j] - xp[j] * D1 / D0 xavg = xp[j] xp_reduced[j] -= self._dynamic_fee(xavg, ys, _fee, feemul) * dx_expected / FEE_DENOMINATOR dy: uint256 = xp_reduced[i] - self.get_y_D(amp, i, xp_reduced, D1) return (dy - 1) / precisions[i] @view @external def calc_withdraw_one_coin(_token_amount: uint256, i: int128) -> uint256: """ @notice Calculate the amount received when withdrawing a single coin @dev Result is the same for underlying or wrapped asset withdrawals @param _token_amount Amount of LP tokens to burn in the withdrawal @param i Index value of the coin to withdraw @return Amount of coin received """ return self._calc_withdraw_one_coin(_token_amount, i) @external @nonreentrant('lock') def remove_liquidity_one_coin( _token_amount: uint256, i: int128, _min_amount: uint256, _use_underlying: bool = False ) -> uint256: """ @notice Withdraw a single coin from the pool @param _token_amount Amount of LP tokens to burn in the withdrawal @param i Index value of the coin to withdraw @param _min_amount Minimum amount of coin to receive @param _use_underlying If True, withdraw underlying assets instead of aTokens @return Amount of coin received """ assert not self.is_killed # dev: is killed dy: uint256 = self._calc_withdraw_one_coin(_token_amount, i) assert dy >= _min_amount, "Not enough coins removed" CurveToken(self.lp_token).burnFrom(msg.sender, _token_amount) # dev: insufficient funds if _use_underlying: LendingPool(LENDING_POOL).withdraw(self.underlying_coins[i], dy, msg.sender) else: assert ERC20(self.coins[i]).transfer(msg.sender, dy) log RemoveLiquidityOne(msg.sender, _token_amount, dy) return dy ### Admin functions ### @external def ramp_A(_future_A: uint256, _future_time: uint256): assert msg.sender == self.owner # dev: only owner assert block.timestamp >= self.initial_A_time + MIN_RAMP_TIME assert _future_time >= block.timestamp + MIN_RAMP_TIME # dev: insufficient time _initial_A: uint256 = self._A() _future_A_p: uint256 = _future_A * A_PRECISION assert _future_A > 0 and _future_A < MAX_A if _future_A_p < _initial_A: assert _future_A_p * MAX_A_CHANGE >= _initial_A else: assert _future_A_p <= _initial_A * MAX_A_CHANGE self.initial_A = _initial_A self.future_A = _future_A_p self.initial_A_time = block.timestamp self.future_A_time = _future_time log RampA(_initial_A, _future_A_p, block.timestamp, _future_time) @external def stop_ramp_A(): assert msg.sender == self.owner # dev: only owner current_A: uint256 = self._A() self.initial_A = current_A self.future_A = current_A self.initial_A_time = block.timestamp self.future_A_time = block.timestamp # now (block.timestamp < t1) is always False, so we return saved A log StopRampA(current_A, block.timestamp) @external def commit_new_fee(new_fee: uint256, new_admin_fee: uint256, new_offpeg_fee_multiplier: uint256): assert msg.sender == self.owner # dev: only owner assert self.admin_actions_deadline == 0 # dev: active action assert new_fee <= MAX_FEE # dev: fee exceeds maximum assert new_admin_fee <= MAX_ADMIN_FEE # dev: admin fee exceeds maximum assert new_offpeg_fee_multiplier * new_fee <= MAX_FEE * FEE_DENOMINATOR # dev: offpeg multiplier exceeds maximum _deadline: uint256 = block.timestamp + ADMIN_ACTIONS_DELAY self.admin_actions_deadline = _deadline self.future_fee = new_fee self.future_admin_fee = new_admin_fee self.future_offpeg_fee_multiplier = new_offpeg_fee_multiplier log CommitNewFee(_deadline, new_fee, new_admin_fee, new_offpeg_fee_multiplier) @external def apply_new_fee(): assert msg.sender == self.owner # dev: only owner assert block.timestamp >= self.admin_actions_deadline # dev: insufficient time assert self.admin_actions_deadline != 0 # dev: no active action self.admin_actions_deadline = 0 _fee: uint256 = self.future_fee _admin_fee: uint256 = self.future_admin_fee _fml: uint256 = self.future_offpeg_fee_multiplier self.fee = _fee self.admin_fee = _admin_fee self.offpeg_fee_multiplier = _fml log NewFee(_fee, _admin_fee, _fml) @external def revert_new_parameters(): assert msg.sender == self.owner # dev: only owner self.admin_actions_deadline = 0 @external def commit_transfer_ownership(_owner: address): assert msg.sender == self.owner # dev: only owner assert self.transfer_ownership_deadline == 0 # dev: active transfer _deadline: uint256 = block.timestamp + ADMIN_ACTIONS_DELAY self.transfer_ownership_deadline = _deadline self.future_owner = _owner log CommitNewAdmin(_deadline, _owner) @external def apply_transfer_ownership(): assert msg.sender == self.owner # dev: only owner assert block.timestamp >= self.transfer_ownership_deadline # dev: insufficient time assert self.transfer_ownership_deadline != 0 # dev: no active transfer self.transfer_ownership_deadline = 0 _owner: address = self.future_owner self.owner = _owner log NewAdmin(_owner) @external def revert_transfer_ownership(): assert msg.sender == self.owner # dev: only owner self.transfer_ownership_deadline = 0 @external def withdraw_admin_fees(): assert msg.sender == self.owner # dev: only owner for i in range(N_COINS): value: uint256 = self.admin_balances[i] if value != 0: assert ERC20(self.coins[i]).transfer(self.admin_fee_receiver, value) self.admin_balances[i] = 0 @external def donate_admin_fees(): """ Just in case admin balances somehow become higher than total (rounding error?) this can be used to fix the state, too """ assert msg.sender == self.owner # dev: only owner self.admin_balances = empty(uint256[N_COINS]) @external def kill_me(): assert msg.sender == self.owner # dev: only owner assert self.kill_deadline > block.timestamp # dev: deadline has passed self.is_killed = True @external def unkill_me(): assert msg.sender == self.owner # dev: only owner self.is_killed = False @external def set_aave_referral(referral_code: uint256): assert msg.sender == self.owner # dev: only owner assert referral_code < 2 ** 16 # dev: uint16 overflow self.aave_referral = referral_code @external def set_reward_receiver(_reward_receiver: address): assert msg.sender == self.owner self.reward_receiver = _reward_receiver @external def set_admin_fee_receiver(_admin_fee_receiver: address): assert msg.sender == self.owner self.admin_fee_receiver = _admin_fee_receiver @external def recover_token(_token: address): """ @notice Transfer arbitrary ERC20's out of the pool @dev Allows the admin to rescue gTokens that accrue from staked GEIST """ assert msg.sender == self.owner assert _token not in self.coins amount: uint256 = ERC20(_token).balanceOf(self) ERC20(_token).transfer(msg.sender, amount)
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"name":"TokenExchange","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"TokenExchangeUnderlying","inputs":[{"name":"buyer","type":"address","indexed":true},{"name":"sold_id","type":"int128","indexed":false},{"name":"tokens_sold","type":"uint256","indexed":false},{"name":"bought_id","type":"int128","indexed":false},{"name":"tokens_bought","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"AddLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[3]","indexed":false},{"name":"fees","type":"uint256[3]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidity","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[3]","indexed":false},{"name":"fees","type":"uint256[3]","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityOne","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amount","type":"uint256","indexed":false},{"name":"coin_amount","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RemoveLiquidityImbalance","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"token_amounts","type":"uint256[3]","indexed":false},{"name":"fees","type":"uint256[3]","indexed":false},{"name":"invariant","type":"uint256","indexed":false},{"name":"token_supply","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"CommitNewAdmin","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"admin","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"NewAdmin","inputs":[{"name":"admin","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"CommitNewFee","inputs":[{"name":"deadline","type":"uint256","indexed":true},{"name":"fee","type":"uint256","indexed":false},{"name":"admin_fee","type":"uint256","indexed":false},{"name":"offpeg_fee_multiplier","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"NewFee","inputs":[{"name":"fee","type":"uint256","indexed":false},{"name":"admin_fee","type":"uint256","indexed":false},{"name":"offpeg_fee_multiplier","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"RampA","inputs":[{"name":"old_A","type":"uint256","indexed":false},{"name":"new_A","type":"uint256","indexed":false},{"name":"initial_time","type":"uint256","indexed":false},{"name":"future_time","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StopRampA","inputs":[{"name":"A","type":"uint256","indexed":false},{"name":"t","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_coins","type":"address[3]"},{"name":"_underlying_coins","type":"address[3]"},{"name":"_pool_token","type":"address"},{"name":"_A","type":"uint256"},{"name":"_fee","type":"uint256"},{"name":"_admin_fee","type":"uint256"},{"name":"_offpeg_fee_multiplier","type":"uint256"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":10374},{"stateMutability":"view","type":"function","name":"A_precise","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":10336},{"stateMutability":"view","type":"function","name":"dynamic_fee","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"}],"outputs":[{"name":"","type":"uint256"}],"gas":21813},{"stateMutability":"view","type":"function","name":"balances","inputs":[{"name":"i","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":7230},{"stateMutability":"view","type":"function","name":"get_virtual_price","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":2701683},{"stateMutability":"view","type":"function","name":"calc_token_amount","inputs":[{"name":"_amounts","type":"uint256[3]"},{"name":"is_deposit","type":"bool"}],"outputs":[{"name":"","type":"uint256"}],"gas":5367778},{"stateMutability":"nonpayable","type":"function","name":"claim_rewards","inputs":[],"outputs":[],"gas":25996},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[3]"},{"name":"_min_mint_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"add_liquidity","inputs":[{"name":"_amounts","type":"uint256[3]"},{"name":"_min_mint_amount","type":"uint256"},{"name":"_use_underlying","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"get_dy","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":6288682},{"stateMutability":"view","type":"function","name":"get_dy_underlying","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":6288712},{"stateMutability":"nonpayable","type":"function","name":"exchange","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":6421406},{"stateMutability":"nonpayable","type":"function","name":"exchange_underlying","inputs":[{"name":"i","type":"int128"},{"name":"j","type":"int128"},{"name":"dx","type":"uint256"},{"name":"min_dy","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":6440292},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[3]"}],"outputs":[{"name":"","type":"uint256[3]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity","inputs":[{"name":"_amount","type":"uint256"},{"name":"_min_amounts","type":"uint256[3]"},{"name":"_use_underlying","type":"bool"}],"outputs":[{"name":"","type":"uint256[3]"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[3]"},{"name":"_max_burn_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_imbalance","inputs":[{"name":"_amounts","type":"uint256[3]"},{"name":"_max_burn_amount","type":"uint256"},{"name":"_use_underlying","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"calc_withdraw_one_coin","inputs":[{"name":"_token_amount","type":"uint256"},{"name":"i","type":"int128"}],"outputs":[{"name":"","type":"uint256"}],"gas":4490420},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_token_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_liquidity_one_coin","inputs":[{"name":"_token_amount","type":"uint256"},{"name":"i","type":"int128"},{"name":"_min_amount","type":"uint256"},{"name":"_use_underlying","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"ramp_A","inputs":[{"name":"_future_A","type":"uint256"},{"name":"_future_time","type":"uint256"}],"outputs":[],"gas":159355},{"stateMutability":"nonpayable","type":"function","name":"stop_ramp_A","inputs":[],"outputs":[],"gas":155272},{"stateMutability":"nonpayable","type":"function","name":"commit_new_fee","inputs":[{"name":"new_fee","type":"uint256"},{"name":"new_admin_fee","type":"uint256"},{"name":"new_offpeg_fee_multiplier","type":"uint256"}],"outputs":[],"gas":149308},{"stateMutability":"nonpayable","type":"function","name":"apply_new_fee","inputs":[],"outputs":[],"gas":141395},{"stateMutability":"nonpayable","type":"function","name":"revert_new_parameters","inputs":[],"outputs":[],"gas":23042},{"stateMutability":"nonpayable","type":"function","name":"commit_transfer_ownership","inputs":[{"name":"_owner","type":"address"}],"outputs":[],"gas":78640},{"stateMutability":"nonpayable","type":"function","name":"apply_transfer_ownership","inputs":[],"outputs":[],"gas":66942},{"stateMutability":"nonpayable","type":"function","name":"revert_transfer_ownership","inputs":[],"outputs":[],"gas":23132},{"stateMutability":"nonpayable","type":"function","name":"withdraw_admin_fees","inputs":[],"outputs":[],"gas":90435},{"stateMutability":"nonpayable","type":"function","name":"donate_admin_fees","inputs":[],"outputs":[],"gas":63261},{"stateMutability":"nonpayable","type":"function","name":"kill_me","inputs":[],"outputs":[],"gas":40415},{"stateMutability":"nonpayable","type":"function","name":"unkill_me","inputs":[],"outputs":[],"gas":23252},{"stateMutability":"nonpayable","type":"function","name":"set_aave_referral","inputs":[{"name":"referral_code","type":"uint256"}],"outputs":[],"gas":38382},{"stateMutability":"nonpayable","type":"function","name":"set_reward_receiver","inputs":[{"name":"_reward_receiver","type":"address"}],"outputs":[],"gas":38415},{"stateMutability":"nonpayable","type":"function","name":"set_admin_fee_receiver","inputs":[{"name":"_admin_fee_receiver","type":"address"}],"outputs":[],"gas":38445},{"stateMutability":"nonpayable","type":"function","name":"recover_token","inputs":[{"name":"_token","type":"address"}],"outputs":[],"gas":15174},{"stateMutability":"view","type":"function","name":"coins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}],"gas":3393},{"stateMutability":"view","type":"function","name":"underlying_coins","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}],"gas":3423},{"stateMutability":"view","type":"function","name":"admin_balances","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"gas":3453},{"stateMutability":"view","type":"function","name":"fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3438},{"stateMutability":"view","type":"function","name":"offpeg_fee_multiplier","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3468},{"stateMutability":"view","type":"function","name":"admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3498},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3528},{"stateMutability":"view","type":"function","name":"lp_token","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3558},{"stateMutability":"view","type":"function","name":"initial_A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3588},{"stateMutability":"view","type":"function","name":"future_A","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3618},{"stateMutability":"view","type":"function","name":"initial_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3648},{"stateMutability":"view","type":"function","name":"future_A_time","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3678},{"stateMutability":"view","type":"function","name":"admin_actions_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3708},{"stateMutability":"view","type":"function","name":"transfer_ownership_deadline","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3738},{"stateMutability":"view","type":"function","name":"future_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3768},{"stateMutability":"view","type":"function","name":"future_admin_fee","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3798},{"stateMutability":"view","type":"function","name":"future_offpeg_fee_multiplier","inputs":[],"outputs":[{"name":"","type":"uint256"}],"gas":3828},{"stateMutability":"view","type":"function","name":"future_owner","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3858},{"stateMutability":"view","type":"function","name":"reward_receiver","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3888},{"stateMutability":"view","type":"function","name":"admin_fee_receiver","inputs":[],"outputs":[{"name":"","type":"address"}],"gas":3918}]
Contract Creation Code
6101606154ac6101403960206154ac60c03960c05160a01c6154a757602060206154ac0160c03960c05160a01c6154a757602060406154ac0160c03960c05160a01c6154a757602060606154ac0160c03960c05160a01c6154a757602060806154ac0160c03960c05160a01c6154a757602060a06154ac0160c03960c05160a01c6154a757602060c06154ac0160c03960c05160a01c6154a7576102a060006003818352015b60006101406102a05160038110156154a757602002015118156154a75760006101a06102a05160038110156154a757602002015118156154a7575b81516001018083528114156100a5575b505060066101405181556101605160018201556101805160028201555060096101a05181556101c05160018201556101e0516002820155506102205160648082028215828483041417156154a757809050905090506015556102205160648082028215828483041417156154a7578090509050905060165561024051600f556102605160115561028051601055336012553360225542624f1a0081818301106154a75780820190509050602055610200516013556102c060006003818352015b60206102c051026101a001516102a05260006004610340527f095ea7b300000000000000000000000000000000000000000000000000000000610360526103406004806020846103a001018260208501600060045af1505080518201915050739fad24f572045c7869117160a571b2e50b10d0686020826103a00101526020810190507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6020826103a0010152602081019050806103a0526103a090508051602001806104408284600060045af1156154a757505060206105006104405161046060006102a0515af1156154a75760203d808211156102af57806102b1565b815b905090506104e0526104e08051602001806102e08284600060045af1156154a757505060006102e0511815610313576102e080602001516000825180602090136154a757809190126154a757806020036101000a8204905090509050156154a7575b5b81516001018083528114156101b0575b505061548f56600436101561000d57613441565b600035601c526000513461515f5763f446c1d081141561004a5760065801613447565b610140526101405160648082049050905060005260206000f35b6376a2f0f08114156100705760065801613447565b610140526101405160005260206000f35b6376a9cd3e8114156102545760043580607f1d8160801d141561515f578090505060243580607f1d8160801d141561515f578090505060016101405264e8d4a510006101605264e8d4a5100061018052602061024060246370a082316101c052306101e0526101dc6001600435600381101561515f5702600601545afa1561515f57601f3d111561515f57600050610240516001600435600381101561515f5702600c015480821061515f5780820390509050610140600435600381101561515f57602002015180820282158284830414171561515f57809050905090506101a052602061026060246370a082316101e05230610200526101fc6001602435600381101561515f5702600601545afa1561515f57601f3d111561515f57600050610260516001602435600381101561515f5702600c015480821061515f5780820390509050610140602435600381101561515f57602002015180820282158284830414171561515f57809050905090506101c0526101405161016051610180516101a0516101c0516101a0516101e0526101c05161020052600f5461022052601054610240526102405161022051610200516101e0516006580161359f565b6102a0526101c0526101a0526101805261016052610140526102a05160005260206000f35b634903b0d18114156102cc5760206101c060246370a0823161014052306101605261015c6001600435600381101561515f5702600601545afa1561515f57601f3d111561515f576000506101c0516001600435600381101561515f5702600c015480821061515f578082039050905060005260206000f35b63bb7b8b8081141561045a5761014051600658016136dd565b61016052610180526101a0526101405261016080516101c05280602001516101e052806040015161020052506101405161016051610180516101a0516101c0516101e0516102005160065801613447565b61022052610200526101e0526101c0526101a05261018052610160526101405261022051610240526101405161016051610180516101a0516101c0516101e0516102005161022051610240516101c051610260526101e05161028052610200516102a052610240516102c0526102c0516102a051610280516102605160065801613a7f565b610320526102405261022052610200526101e0526101c0526101a052610180526101605261014052610320516101405260206101e060046318160ddd6101805261019c6013545afa1561515f57601f3d111561515f576000506101e0516101605261014051670de0b6b3a764000080820282158284830414171561515f57809050905090506101605180801561515f5782049050905060005260206000f35b633883e1198114156107275760643560011c61515f57610140516101605161018051600658016136dd565b6101a0526101c0526101e0526101805261016052610140526101a0805161014052806020015161016052806040015161018052506101405161016051610180516101a05160065801613447565b6101c0526101a0526101805261016052610140526101c0516101a0526101405161016051610180516101a0516101c051610140516101e052610160516102005261018051610220526101a051610240526102405161022051610200516101e05160065801613a7f565b6102a0526101c0526101a0526101805261016052610140526102a0516101c0526101e060006003818352015b606435156105b1576101406101e051600381101561515f5760200201805160046101e051600381101561515f576020020135818183011061515f57808201905090508152506105ed565b6101406101e051600381101561515f5760200201805160046101e051600381101561515f57602002013580821061515f57808203905090508152505b5b8151600101808352811415610567575b50506101405161016051610180516101a0516101c0516101e0516101405161020052610160516102205261018051610240526101a051610260526102605161024051610220516102005160065801613a7f565b6102c0526101e0526101c0526101a0526101805261016052610140526102c0516101e052602061028060046318160ddd6102205261023c6013545afa1561515f57601f3d111561515f576000506102805161020052600061022052606435156106d3576101e0516101c05180821061515f5780820390509050610220526106ee565b6101c0516101e05180821061515f5780820390509050610220525b610220516102005180820282158284830414171561515f57809050905090506101c05180801561515f5782049050905060005260206000f35b63e6f1daf28114156109415760215461014052600061014051181561093f5760006004610160527f8e2eba0900000000000000000000000000000000000000000000000000000000610180526101606004806020846101c001018260208501600060045af1505080518201915050306020826101c001015260208101905060406020826101c001015260208101905060036020826101c00101526020810190506006546020826101c00101526020810190506007546020826101c00101526020810190506008546020826101c0010152602081019050806101c0526101c090508051602001806102e08284600060045af11561515f575050600060006102e051610300600073297fddc5c33ef988dd03bd13e162ae084ea1fe575af11561515f577349c93a95dbcc9a6a4d8f77e59c038ce5020e82f83b1561515f5760006000600463e9fad8ee6101605261017c60007349c93a95dbcc9a6a4d8f77e59c038ce5020e82f85af11561515f57602061020060246370a0823161018052306101a05261019c73d8321aa83fb0a4ecd6348d4577431310a6e0814d5afa1561515f57601f3d111561515f576000506102005161016052600061016051111561093e576020610220604463a9059cbb61018052610140516101a052610160516101c05261019c600073d8321aa83fb0a4ecd6348d4577431310a6e0814d5af11561515f57601f3d111561515f57600050610220511561515f575b5b005b634515cef381141561095857600061014052610983565b632b6e993a81141561097e5760843560011c61515f576020608461014037600050610983565b61148a565b60005461515f576001600055601f5461515f57610140516101605160065801613447565b61018052610160526101405261018051610160526101405161016051610180516101a0516101c051600658016136dd565b6101e05261020052610220526101c0526101a0526101805261016052610140526101e080516101805280602001516101a05280604001516101c052506013546101e052602061028060046318160ddd6102205261023c6101e0515afa1561515f57601f3d111561515f5760005061028051610200526000610220526000610200511815610ae5576101405161016051610180516101a0516101c0516101e051610200516102205161018051610240526101a051610260526101c05161028052610160516102a0526102a05161028051610260516102405160065801613a7f565b6103005261022052610200526101e0526101c0526101a05261018052610160526101405261030051610220525b61018051610240526101a051610260526101c051610280526102a060006003818352015b61020051610b2e57600060046102a051600381101561515f576020020135181561515f575b6102406102a051600381101561515f5760200201805160046102a051600381101561515f576020020135818183011061515f57808201905090508152505b8151600101808352811415610b09575b50506101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a051610240516102c052610260516102e0526102805161030052610160516103205261032051610300516102e0516102c05160065801613a7f565b610380526102a05261028052610260526102405261022052610200526101e0526101c0526101a052610180526101605261014052610380516102a052610220516102a051111561515f576080366102c0376000610200511815610ffa57610220516102a051818183011061515f578082019050905060038082049050905061034052600f54600380820282158284830414171561515f578090509050905060088082049050905061036052601054610380526011546103a05260006103c0526103e060006003818352015b6102a0516101806103e051600381101561515f57602002015180820282158284830414171561515f57809050905090506102205180801561515f57820490509050610400526102406103e051600381101561515f5760200201516104205261042051610400511115610d3d57610400516104205180821061515f57808203905090506103c052610d58565b610420516104005180821061515f57808203905090506103c0525b6101806103e051600381101561515f57602002015161042051818183011061515f578082019050905061044052610140610460525b61046051516020610460510161046052610460610460511015610daf57610d8d565b6104405161048052610340516104a052610360516104c052610380516104e0526104e0516104c0516104a051610480516006580161359f565b61054052610440610460525b610460515260206104605103610460526101406104605110610e1557610df4565b610540516103c05180820282158284830414171561515f57809050905090506402540be400808204905090506102c06103e051600381101561515f57602002015260006103a0511815610ec85760016103e051600381101561515f5702600c0180546102c06103e051600381101561515f5760200201516103a05180820282158284830414171561515f57809050905090506402540be40080820490509050818183011061515f57808201905090508155505b610420516102c06103e051600381101561515f57602002015180821061515f57808203905090506102406103e051600381101561515f5760200201525b8151600101808352811415610cb2575b5050610140610400525b61040051516020610400510161040052610400610400511015610f4157610f1f565b61024051610420526102605161044052610280516104605261016051610480526104805161046051610440516104205160065801613a7f565b6104e0526103e0610400525b610400515260206104005103610400526101406104005110610fa757610f86565b6104e0516103e052610200516103e0516102205180821061515f578082039050905080820282158284830414171561515f57809050905090506102205180801561515f5782049050905061032052611003565b6102a051610320525b606435610320511015611055576308c379a0610340526020610360526014610380527f536c697070616765207363726577656420796f750000000000000000000000006103a05261038050606461035cfd5b61014051156112db576014546103405261036060006003818352015b600461036051600381101561515f5760200201356103805260006103805118156112c357600161036051600381101561515f5702600901546103a05260006004610420527f23b872dd000000000000000000000000000000000000000000000000000000006104405261042060048060208461048001018260208501600060045af1505080518201915050336020826104800101526020810190503060208261048001015260208101905061038051602082610480010152602081019050806104805261048090508051602001806105408284600060045af11561515f57505060206106206105405161056060006103a0515af11561515f5760203d8082111561117b578061117d565b815b90509050610600526106008051602001806103c08284600060045af11561515f57505060006103c05118156111df576103c0806020015160008251806020901361515f578091901261515f57806020036101000a82049050905090501561515f575b60006004610420527fe8eda9df000000000000000000000000000000000000000000000000000000006104405261042060048060208461048001018260208501600060045af15050805182019150506103a051602082610480010152602081019050610380516020826104800101526020810190503060208261048001015260208101905061034051602082610480010152602081019050806104805261048090508051602001806105608284600060045af11561515f57505060006000610560516105806000739fad24f572045c7869117160a571b2e50b10d0685af11561515f575b5b8151600101808352811415611071575b5050611377565b61034060006003818352015b600461034051600381101561515f57602002013561036052600061036051181561136357602061044060646323b872dd61038052336103a052306103c052610360516103e05261039c6000600161034051600381101561515f5702600601545af11561515f57601f3d111561515f57600050610440511561515f575b5b81516001018083528114156112e7575b50505b60206103e060446340c10f19610340523361036052610320516103805261035c60006101e0515af11561515f57601f3d111561515f576000506103e050337f423f6495a08fc652425cf4ed0d1f9e37e571d9b9529b1c1c23cce780b2e7df0d6103408080808080600435815250506020810190508080602435815250506020810190508080604435815250505050606081019050808080806102c0518152505060208101905080806102e0518152505060208101905080806103005181525050505060608101905080806102a0518152505060208101905080806102005161032051818183011061515f57808201905090508152505061010090509050610340a261032051600052600060005560206000f35b635e0d443f8114156114fb5760043580607f1d8160801d141561515f578090505060243580607f1d8160801d141561515f578090505060043561014052602435610160526044356101805261018051610160516101405160065801613fb7565b6101e0526101e05160005260206000f35b6307211ef781141561156c5760043580607f1d8160801d141561515f578090505060243580607f1d8160801d141561515f578090505060043561014052602435610160526044356101805261018051610160516101405160065801613fb7565b6101e0526101e05160005260206000f35b633df021248114156117825760015461515f57600160015560043580607f1d8160801d141561515f578090505060243580607f1d8160801d141561515f57809050506101405160043561016052602435610180526044356101a0526101a05161018051610160516006580161436a565b61020052610140526102005161014052606435610140511015611663576308c379a061016052602061018052602e6101a0527f45786368616e676520726573756c74656420696e20666577657220636f696e736101c0527f207468616e2065787065637465640000000000000000000000000000000000006101e0526101a050608461017cfd5b602061022060646323b872dd610160523361018052306101a0526044356101c05261017c60006001600435600381101561515f5702600601545af11561515f57601f3d111561515f57600050610220511561515f576020610200604463a9059cbb610160523361018052610140516101a05261017c60006001602435600381101561515f5702600601545af11561515f57601f3d111561515f57600050610200511561515f57337f8b3e96f2b889fa771c53c981b40daf005f63f637f1869f707052d15a3dd971406101608080806004358152505060208101905080806044358152505060208101905080806024358152505060208101905080806101405181525050608090509050610160a261014051600052600060015560206000f35b63a6417ed6811415611b8a5760025461515f57600160025560043580607f1d8160801d141561515f578090505060243580607f1d8160801d141561515f57809050506101405160043561016052602435610180526044356101a0526101a05161018051610160516006580161436a565b61020052610140526102005161014052606435610140511015611879576308c379a061016052602061018052602e6101a0527f45786368616e676520726573756c74656420696e20666577657220636f696e736101c0527f207468616e2065787065637465640000000000000000000000000000000000006101e0526101a050608461017cfd5b6001600435600381101561515f57026009015461016052600060046101e0527f23b872dd00000000000000000000000000000000000000000000000000000000610200526101e060048060208461024001018260208501600060045af15050805182019150503360208261024001015260208101905030602082610240010152602081019050604435602082610240010152602081019050806102405261024090508051602001806103008284600060045af11561515f57505060206103e0610300516103206000610160515af11561515f5760203d8082111561195d578061195f565b815b905090506103c0526103c08051602001806101808284600060045af11561515f57505060006101805118156119c157610180806020015160008251806020901361515f578091901261515f57806020036101000a82049050905090501561515f575b600060046101e0527fe8eda9df00000000000000000000000000000000000000000000000000000000610200526101e060048060208461024001018260208501600060045af15050805182019150506101605160208261024001015260208101905060443560208261024001015260208101905030602082610240010152602081019050601454602082610240010152602081019050806102405261024090508051602001806103208284600060045af11561515f57505060006000610320516103406000739fad24f572045c7869117160a571b2e50b10d0685af11561515f57739fad24f572045c7869117160a571b2e50b10d0683b1561515f576000600060646369328dec6101e0526001602435600381101561515f57026009015461020052610140516102205233610240526101fc6000739fad24f572045c7869117160a571b2e50b10d0685af11561515f57337fd013ca23e77a65003c2c659c5442c00c805371b7fc1ebd4c206c41d1536bd90b6101e080808060043581525050602081019050808060443581525050602081019050808060243581525050602081019050808061014051815250506080905090506101e0a261014051600052600060025560206000f35b63ecb586a5811415611ba157600061014052611bcc565b63fce64736811415611bc75760843560011c61515f576020608461014037600050611bcc565b611f2c565b60035461515f5760016003556101405161016051610180516101a051600658016136dd565b6101c0526101e052610200526101a0526101805261016052610140526101c080516101605280602001516101805280604001516101a052506013546101c052602061026060046318160ddd6102005261021c6101c0515afa1561515f57601f3d111561515f57600050610260516101e05260206102a060446379cc67906102005233610220526004356102405261021c60006101c0515af11561515f57601f3d111561515f576000506102a05061020060006003818352015b61016061020051600381101561515f57602002015160043580820282158284830414171561515f57809050905090506101e05180801561515f5782049050905061022052602461020051600381101561515f576020020135610220511015611d76576308c379a0610240526020610260526030610280527f5769746864726177616c20726573756c74656420696e20666577657220636f696102a0527f6e73207468616e206578706563746564000000000000000000000000000000006102c05261028050608461025cfd5b6102205161016061020051600381101561515f5760200201526101405115611e0d57739fad24f572045c7869117160a571b2e50b10d0683b1561515f576000600060646369328dec61024052600161020051600381101561515f570260090154610260526102205161028052336102a05261025c6000739fad24f572045c7869117160a571b2e50b10d0685af11561515f57611e60565b60206102e0604463a9059cbb610240523361026052610220516102805261025c6000600161020051600381101561515f5702600601545af11561515f57601f3d111561515f576000506102e0511561515f575b5b8151600101808352811415611caa575b5050337fa49d4cf02656aebf8c771f5a8585638a2a15ee6c97cf7205d4208ed7c1df252d610200808080808061016051815250506020810190508080610180518152505060208101905080806101a0518152505050506060810190508080808060008152505060208101905080806000815250506020810190508080600081525050505060608101905080806101e05160043580821061515f57808203905090508152505060e090509050610200a260006003556060610160f35b639fdaea0c811415611f4357600061014052611f6e565b635b8369f5811415611f695760843560011c61515f576020608461014037600050611f6e565b6127fc565b60045461515f576001600455601f5461515f57610140516101605160065801613447565b61018052610160526101405261018051610160526101405161016051610180516101a0516101c051600658016136dd565b6101e05261020052610220526101c0526101a0526101805261016052610140526101e080516101805280602001516101a05280604001516101c052506101405161016051610180516101a0516101c0516101e05161018051610200526101a051610220526101c0516102405261016051610260526102605161024051610220516102005160065801613a7f565b6102c0526101e0526101c0526101a0526101805261016052610140526102c0516101e05261018051610200526101a051610220526101c0516102405261026060006003818352015b61020061026051600381101561515f57602002018051600461026051600381101561515f57602002013580821061515f57808203905090508152505b8151600101808352811415612098575b50506101405161016051610180516101a0516101c0516101e051610200516102205161024051610260516102005161028052610220516102a052610240516102c052610160516102e0526102e0516102c0516102a0516102805160065801613a7f565b61034052610260526102405261022052610200526101e0526101c0526101a05261018052610160526101405261034051610260526101e05161026051818183011061515f5780820190509050600380820490509050610280526013546102a052602061034060046318160ddd6102e0526102fc6102a0515afa1561515f57601f3d111561515f57600050610340516102c05260006102c051181561515f57600f54600380820282158284830414171561515f57809050905090506008808204905090506102e0526010546103005260115461032052606036610340376103a060006003818352015b610260516101806103a051600381101561515f57602002015180820282158284830414171561515f57809050905090506101e05180801561515f578204905090506103c0526102006103a051600381101561515f5760200201516103e0526000610400526103e0516103c05111156122c0576103c0516103e05180821061515f5780820390509050610400526122db565b6103e0516103c05180821061515f5780820390509050610400525b6103e0516101806103a051600381101561515f576020020151818183011061515f578082019050905061042052610140610440525b6104405151602061044051016104405261044061044051101561233257612310565b610420516104605261028051610480526102e0516104a052610300516104c0526104c0516104a05161048051610460516006580161359f565b61052052610420610440525b61044051526020610440510361044052610140610440511061239857612377565b610520516104005180820282158284830414171561515f57809050905090506402540be400808204905090506103406103a051600381101561515f576020020152600061032051181561244b5760016103a051600381101561515f5702600c0180546103406103a051600381101561515f5760200201516103205180820282158284830414171561515f57809050905090506402540be40080820490509050818183011061515f57808201905090508155505b6102006103a051600381101561515f576020020180516103406103a051600381101561515f57602002015180821061515f57808203905090508152505b815160010180835281141561222f575b50506101406103c0525b6103c0515160206103c051016103c0526103c06103c05110156124c4576124a2565b610200516103e0526102205161040052610240516104205261016051610440526104405161042051610400516103e05160065801613a7f565b6104a0526103a06103c0525b6103c0515260206103c051036103c0526101406103c0511061252a57612509565b6104a0516103a0526101e0516103a05180821061515f57808203905090506102c05180820282158284830414171561515f57809050905090506101e05180801561515f578204905090506103c05260006103c051181561515f576064356103c05111156125d6576308c379a06103e0526020610400526014610420527f536c697070616765207363726577656420796f75000000000000000000000000610440526104205060646103fcfd5b602061048060446379cc67906103e05233610400526103c051610420526103fc60006102a0515af11561515f57601f3d111561515f57600050610480506103e060006003818352015b60046103e051600381101561515f5760200201356104005260006104005118156127155761014051156126c157739fad24f572045c7869117160a571b2e50b10d0683b1561515f576000600060646369328dec6104205260016103e051600381101561515f570260090154610440526104005161046052336104805261043c6000739fad24f572045c7869117160a571b2e50b10d0685af11561515f57612714565b60206104c0604463a9059cbb610420523361044052610400516104605261043c600060016103e051600381101561515f5702600601545af11561515f57601f3d111561515f576000506104c0511561515f575b5b5b815160010180835281141561261f575b5050337f173599dbf9c6ca6f7c3b590df07ae98a45d74ff54065505141e7de6c46a624c26103e08080808080600435815250506020810190508080602435815250506020810190508080604435815250505050606081019050808080806103405181525050602081019050808061036051815250506020810190508080610380518152505050506060810190508080610260518152505060208101905080806102c0516103c05180821061515f578082039050905081525050610100905090506103e0a26103c051600052600060045560206000f35b63cc2b27d781141561284d5760243580607f1d8160801d141561515f57809050506004356101405260243561016052610160516101405160065801614ab9565b6101c0526101c05160005260206000f35b631a4d01d28114156128645760006101405261288f565b63517a55a381141561288a5760643560011c61515f57602060646101403760005061288f565b612aa9565b60055461515f57600160055560243580607f1d8160801d141561515f5780905050601f5461515f576101405161016051600435610180526024356101a0526101a0516101805160065801614ab9565b6102005261016052610140526102005161016052604435610160511015612944576308c379a06101805260206101a05260186101c0527f4e6f7420656e6f75676820636f696e732072656d6f76656400000000000000006101e0526101c050606461019cfd5b602061022060446379cc679061018052336101a0526004356101c05261019c60006013545af11561515f57601f3d111561515f576000506102205061014051156129fc57739fad24f572045c7869117160a571b2e50b10d0683b1561515f576000600060646369328dec610180526001602435600381101561515f5702600901546101a052610160516101c052336101e05261019c6000739fad24f572045c7869117160a571b2e50b10d0685af11561515f57612a4e565b6020610220604463a9059cbb61018052336101a052610160516101c05261019c60006001602435600381101561515f5702600601545af11561515f57601f3d111561515f57600050610220511561515f575b337f9e96dd3b997a2a257eec4df9bb6eaf626e206df5f543bd963682d143300be3106101808080806004358152505060208101905080806101605181525050604090509050610180a261016051600052600060055560206000f35b633c157e64811415612c355760125433141561515f5760175462015180818183011061515f5780820190509050421061515f574262015180818183011061515f57808201905090506024351061515f576101405160065801613447565b61016052610140526101605161014052600435606480820282158284830414171561515f57809050905090506101605260006004351115612b4e57620f424060043510612b51565b60005b1561515f5761014051610160511015612b8f576101405161016051600a80820282158284830414171561515f57809050905090501061515f57612bb6565b61014051600a80820282158284830414171561515f5780905090509050610160511161515f575b6101405160155561016051601655426017556024356018557fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c25461018080808061014051815250506020810190508080610160518152505060208101905080804281525050602081019050808060243581525050608090509050610180a1005b63551a6588811415612cc65760125433141561515f576101405160065801613447565b61016052610140526101605161014052610140516015556101405160165542601755426018557f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc201938610160808080610140518152505060208101905080804281525050604090509050610160a1005b630746dd5a811415612db95760125433141561515f5760195461515f5764012a05f2006004351161515f576402540be4006024351161515f576802b5e3af16b188000060443560043580820282158284830414171561515f57809050905090501161515f57426203f480818183011061515f57808201905090506101405261014051601955600435601b55602435601c55604435601d55610140517fe347cde074ab87e09449fa2b03e8f2cf79094cb1265f4c914365d2247d4147a361016080808060043581525050602081019050808060243581525050602081019050808060443581525050606090509050610160a2005b634f12fe97811415612e6d5760125433141561515f57601954421061515f576000601954181561515f576000601955601b5461014052601c5461016052601d546101805261014051600f5561016051601155610180516010557fcfca96e0fef3432146913b2a5a2268a55d3f475fe057e7ffde1082b77693f4f36101a0808080610140518152505060208101905080806101605181525050602081019050808061018051815250506060905090506101a0a1005b63226840fb811415612e8a5760125433141561515f576000601955005b636b441a40811415612f0f5760043560a01c61515f5760125433141561515f57601a5461515f57426203f480818183011061515f57808201905090506101405261014051601a55600435601e55600435610140517f181aa3aa17d4cbf99265dd4443eba009433d3cde79d60164fde1d1a192beb93561016080600090509050610160a3005b636a1c05ae811415612f815760125433141561515f57601a54421061515f576000601a54181561515f576000601a55601e546101405261014051601255610140517f71614071b88dee5e0b2ae578a9dd7b2ebbe9ae832ba419dc0242cd065a290b6c61016080600090509050610160a2005b6386fbf193811415612f9e5760125433141561515f576000601a55005b6330c540858114156130645760125433141561515f5761014060006003818352015b600161014051600381101561515f5702600c015461016052600061016051181561304f576020610220604463a9059cbb610180526022546101a052610160516101c05261019c6000600161014051600381101561515f5702600601545af11561515f57601f3d111561515f57600050610220511561515f576000600161014051600381101561515f5702600c01555b5b8151600101808352811415612fc0575b5050005b63524c39018114156130915760125433141561515f57600c60008155600060018201556000600282015550005b63e36988538114156130b85760125433141561515f5742602054111561515f576001601f55005b633046f9728114156130d55760125433141561515f576000601f55005b63b6aa64c58114156131005760125433141561515f5762010000600435101561515f57600435601455005b63c51b88618114156131285760043560a01c61515f5760125433141561515f57600435602155005b637242e5248114156131505760043560a01c61515f5760125433141561515f57600435602255005b63a3c91c9581141561322f5760043560a01c61515f5760125433141561515f5760006101405261014061012060006003818352015b6101205160060154600435141561319f57600183526131b0565b5b8151600101808352811415613185575b5050506101405161515f5760206101e060246370a0823161016052306101805261017c6004355afa1561515f57601f3d111561515f576000506101e051610140526020610200604463a9059cbb610160523361018052610140516101a05261017c60006004355af11561515f57601f3d111561515f5760005061020050005b63c6610657811415613257576001600435600381101561515f57026006015460005260206000f35b63b9947eb081141561327f576001600435600381101561515f57026009015460005260206000f35b63e2e7d2648114156132a7576001600435600381101561515f5702600c015460005260206000f35b63ddca3f438114156132bf57600f5460005260206000f35b638edfdd5f8114156132d75760105460005260206000f35b63fee3f7f98114156132ef5760115460005260206000f35b638da5cb5b8114156133075760125460005260206000f35b6382c6306681141561331f5760135460005260206000f35b635409491a8114156133375760155460005260206000f35b63b4b577ad81141561334f5760165460005260206000f35b632081066c8114156133675760175460005260206000f35b631405228881141561337f5760185460005260206000f35b63405e28f88114156133975760195460005260206000f35b63e0a0b5868114156133af57601a5460005260206000f35b6358680d0b8114156133c757601b5460005260206000f35b63e38244628114156133df57601c5460005260206000f35b631e4c4ef88114156133f757601d5460005260206000f35b631ec0cdc181141561340f57601e5460005260206000f35b63b618ba628114156134275760215460005260206000f35b636e42e4d281141561343f5760225460005260206000f35b505b60006000fd5b6101405260185461016052601654610180526101605142101561358d576015546101a0526017546101c0526101a051610180511115613507576101a051610180516101a05180821061515f5780820390509050426101c05180821061515f578082039050905080820282158284830414171561515f5780905090509050610160516101c05180821061515f578082039050905080801561515f57820490509050818183011061515f57808201905090506000526000516101405156613588565b6101a0516101a0516101805180821061515f5780820390509050426101c05180821061515f578082039050905080820282158284830414171561515f5780905090509050610160516101c05180821061515f578082039050905080801561515f5782049050905080821061515f578082039050905060005260005161014051565b61359d565b6101805160005260005161014051565b005b6101c0526101405261016052610180526101a0526402540be4006101a051116135d657610180516000526000516101c051566136db565b6101405161016051818183011061515f57808201905090506101e0526101e080516101e05180820282158284830414171561515f57809050905090508152506101a0516101805180820282158284830414171561515f57809050905090506101a0516402540be40080821061515f5780820390509050600480820282158284830414171561515f57809050905090506101405180820282158284830414171561515f57809050905090506101605180820282158284830414171561515f57809050905090506101e05180801561515f578204905090506402540be400818183011061515f578082019050905080801561515f578204905090506000526000516101c051565b005b61014052606036610160376101c060006003818352015b602061026060246370a082316101e05230610200526101fc60016101c051600381101561515f5702600601545afa1561515f57601f3d111561515f576000506102605160016101c051600381101561515f5702600c015480821061515f57808203905090506101606101c051600381101561515f5760200201525b81516001018083528114156136f4575b505060606101c0525b60006101c05111613798576137b4565b60206101c05103610160015160206101c051036101c052613788565b61014051565b6101c0526101405261016052610180526101a05260006101e05261022060006003818352015b602061022051026101400151610200526101e0805161020051818183011061515f57808201905090508152505b81516001018083528114156137e0575b50506101e0516138355760006000526000516101c051565b6000610200526101e051610220526101a051600380820282158284830414171561515f578090509050905061024052610260600060ff818352015b61022051610280526102c060006003818352015b60206102c0510261014001516102a052610280516102205180820282158284830414171561515f57809050905090506102a051600380820282158284830414171561515f57809050905090506001818183011061515f578082019050905080801561515f57820490509050610280525b8151600101808352811415613884575b50506102205161020052610240516101e05180820282158284830414171561515f578090509050905060648082049050905061028051600380820282158284830414171561515f5780905090509050818183011061515f57808201905090506102205180820282158284830414171561515f578090509050905061024051606480821061515f57808203905090506102205180820282158284830414171561515f578090509050905060648082049050905060046102805180820282158284830414171561515f5780905090509050818183011061515f578082019050905080801561515f578204905090506102205261020051610220511115613a36576001610220516102005180821061515f578082039050905011613a31576102205160005250506000516101c051565b613a66565b6001610200516102205180821061515f578082039050905011613a65576102205160005250506000516101c051565b5b5b8151600101808352811415613870575b505060006000fd5b6101c0526101405261016052610180526101a05260016101e05264e8d4a510006102005264e8d4a510006102205261024060006003818352015b6101e061024051600381101561515f5760200201805161014061024051600381101561515f57602002015180820282158284830414171561515f57809050905090508152505b8151600101808352811415613ab9575b50506101405161016051610180516101a0516101c0516101e05161020051610220516101e05161024052610200516102605261022051610280526101a0516102a0526102a051610280516102605161024051600658016137ba565b6103005261022052610200526101e0526101c0526101a052610180526101605261014052610300516000526000516101c051565b610200526101405261016052610180526101a0526101c0526101e0526101605161014051181561515f576000610160511261515f57600361016051121561515f576000610140511261515f57600361014051121561515f576101405161016051610180516101a0516101c0516101e051610200516102205160065801613447565b6102405261022052610200526101e0526101c0526101a05261018052610160526101405261024051610220526101405161016051610180516101a0516101c0516101e0516102005161022051610240516101a051610260526101c051610280526101e0516102a052610220516102c0526102c0516102a0516102805161026051600658016137ba565b610320526102405261022052610200526101e0526101c0526101a052610180526101605261014052610320516102405261022051600380820282158284830414171561515f57809050905090506102605261024051610280526060366102a03761030060006003818352015b61014051610300511415613d2f57610180516102c052613d61565b61016051610300511815613d5b576101a061030051600381101561515f5760200201516102c052613d60565b613dcb565b5b6102a080516102c051818183011061515f5780820190509050815250610280516102405180820282158284830414171561515f57809050905090506102c051600380820282158284830414171561515f578090509050905080801561515f57820490509050610280525b8151600101808352811415613d14575b5050610280516102405180820282158284830414171561515f5780905090509050606480820282158284830414171561515f578090509050905061026051600380820282158284830414171561515f578090509050905080801561515f57820490509050610280526102a05161024051606480820282158284830414171561515f57809050905090506102605180801561515f57820490509050818183011061515f5780820190509050610300526102405161032052610340600060ff818352015b610320516102e052610320516103205180820282158284830414171561515f578090509050905061028051818183011061515f578082019050905060026103205180820282158284830414171561515f578090509050905061030051818183011061515f57808201905090506102405180821061515f578082039050905080801561515f57820490509050610320526102e051610320511115613f6e576001610320516102e05180821061515f578082039050905011613f695761032051600052505060005161020051565b613f9e565b60016102e0516103205180821061515f578082039050905011613f9d5761032051600052505060005161020051565b5b5b8151600101808352811415613e9d575b505060006000fd5b6101a0526101405261016052610180526101405161016051610180516101a0516101c0516101e05161020051600658016136dd565b610220526102405261026052610200526101e0526101c0526101a05261018052610160526101405261022080516101c05280602001516101e0528060400151610200525060016102205264e8d4a510006102405264e8d4a510006102605261028060006003818352015b6101c061028051600381101561515f5760200201805161022061028051600381101561515f57602002015180820282158284830414171561515f57809050905090508152505b8151600101808352811415614056575b50506101c061014051600381101561515f5760200201516101805161022061014051600381101561515f57602002015180820282158284830414171561515f5780905090509050818183011061515f5780820190509050610280526101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a051610140516102c052610160516102e05261028051610300526101c051610320526101e051610340526102005161036052610360516103405161032051610300516102e0516102c05160065801613b9e565b6103c0526102a05261028052610260526102405261022052610200526101e0526101c0526101a0526101805261016052610140526103c0516102a0526101c061016051600381101561515f5760200201516102a05180821061515f578082039050905061022061016051600381101561515f57602002015180801561515f578204905090506102c0526101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e0516101c061014051600381101561515f57602002015161028051818183011061515f5780820190509050600280820490509050610300526101c061016051600381101561515f5760200201516102a051818183011061515f578082019050905060028082049050905061032052600f546103405260105461036052610360516103405161032051610300516006580161359f565b6103c0526102e0526102c0526102a05261028052610260526102405261022052610200526101e0526101c0526101a0526101805261016052610140526103c0516102c05180820282158284830414171561515f57809050905090506402540be400808204905090506102e0526102c0516102e05180821061515f57808203905090506000526000516101a051565b6101a052610140526101605261018052601f5461515f576101405161016051610180516101a0516101c0516101e05161020051600658016136dd565b610220526102405261026052610200526101e0526101c0526101a05261018052610160526101405261022080516101c05280602001516101e0528060400151610200525060016102205264e8d4a510006102405264e8d4a510006102605261028060006003818352015b6101c061028051600381101561515f5760200201805161022061028051600381101561515f57602002015180820282158284830414171561515f57809050905090508152505b8151600101808352811415614410575b50506101c061014051600381101561515f5760200201516101805161022061014051600381101561515f57602002015180820282158284830414171561515f5780905090509050818183011061515f5780820190509050610280526101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a051610140516102c052610160516102e05261028051610300526101c051610320526101e051610340526102005161036052610360516103405161032051610300516102e0516102c05160065801613b9e565b6103c0526102a05261028052610260526102405261022052610200526101e0526101c0526101a0526101805261016052610140526103c0516102a0526101c061016051600381101561515f5760200201516102a05180821061515f57808203905090506102c0526102c0516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516102e0516101c061014051600381101561515f57602002015161028051818183011061515f5780820190509050600280820490509050610300526101c061016051600381101561515f5760200201516102a051818183011061515f578082019050905060028082049050905061032052600f546103405260105461036052610360516103405161032051610300516006580161359f565b6103c0526102e0526102c0526102a05261028052610260526102405261022052610200526101e0526101c0526101a0526101805261016052610140526103c05180820282158284830414171561515f57809050905090506402540be400808204905090506102e05260115461030052600061030051181561477f576102e0516103005180820282158284830414171561515f57809050905090506402540be4008082049050905061032052600061032051181561477e57600161016051600381101561515f5702600c0180546103205161022061016051600381101561515f57602002015180801561515f57820490509050818183011061515f57808201905090508155505b5b6102c0516102e05180821061515f578082039050905061022061016051600381101561515f57602002015180801561515f578204905090506000526000516101a051565b610200526101405261016052610180526101a0526101c0526101e0526000610160511261515f57600361016051121561515f5761014051600380820282158284830414171561515f5780905090509050610220526101e05161024052606036610260376102c060006003818352015b610160516102c051181561485e576101806102c051600381101561515f57602002015161028052614863565b6148cd565b610260805161028051818183011061515f5780820190509050815250610240516101e05180820282158284830414171561515f578090509050905061028051600380820282158284830414171561515f578090509050905080801561515f57820490509050610240525b8151600101808352811415614832575b5050610240516101e05180820282158284830414171561515f5780905090509050606480820282158284830414171561515f578090509050905061022051600380820282158284830414171561515f578090509050905080801561515f5782049050905061024052610260516101e051606480820282158284830414171561515f57809050905090506102205180801561515f57820490509050818183011061515f57808201905090506102c0526101e0516102e052610300600060ff818352015b6102e0516102a0526102e0516102e05180820282158284830414171561515f578090509050905061024051818183011061515f578082019050905060026102e05180820282158284830414171561515f57809050905090506102c051818183011061515f57808201905090506101e05180821061515f578082039050905080801561515f578204905090506102e0526102a0516102e0511115614a705760016102e0516102a05180821061515f578082039050905011614a6b576102e051600052505060005161020051565b614aa0565b60016102a0516102e05180821061515f578082039050905011614a9f576102e051600052505060005161020051565b5b5b815160010180835281141561499f575b505060006000fd5b6101805261014052610160526101405161016051610180516101a05160065801613447565b6101c0526101a0526101805261016052610140526101c0516101a0526101405161016051610180516101a0516101c0516101e05161020051600658016136dd565b610220526102405261026052610200526101e0526101c0526101a05261018052610160526101405261022080516101c05280602001516101e0528060400151610200525060016102205264e8d4a510006102405264e8d4a510006102605261028060006003818352015b6101c061028051600381101561515f5760200201805161022061028051600381101561515f57602002015180820282158284830414171561515f57809050905090508152505b8151600101808352811415614b89575b50506101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516101c0516102a0526101e0516102c052610200516102e0526101a05161030052610300516102e0516102c0516102a051600658016137ba565b6103605261028052610260526102405261022052610200526101e0526101c0526101a052610180526101605261014052610360516102805261028051610140516102805180820282158284830414171561515f5780905090509050602061032060046318160ddd6102c0526102dc6013545afa1561515f57601f3d111561515f576000506103205180801561515f5782049050905080821061515f57808203905090506102a0526101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516102c0516101a0516102e05261016051610300526101c051610320526101e0516103405261020051610360526102a0516103805261038051610360516103405161032051610300516102e051600658016147c3565b6103e0526102c0526102a05261028052610260526102405261022052610200526101e0526101c0526101a0526101805261016052610140526103e0516102c0526101c0516102e0526101e051610300526102005161032052610280516102a051818183011061515f578082019050905060068082049050905061034052600f54600380820282158284830414171561515f578090509050905060088082049050905061036052601054610380526103a060006003818352015b6040366103c037610160516103a0511415614ed2576101c06103a051600381101561515f5760200201516102a05180820282158284830414171561515f57809050905090506102805180801561515f578204905090506102c05180821061515f57808203905090506103c0526101c06103a051600381101561515f5760200201516102c051818183011061515f57808201905090506002808204905090506103e052614f54565b6101c06103a051600381101561515f5760200201516101c06103a051600381101561515f5760200201516102a05180820282158284830414171561515f57809050905090506102805180801561515f5782049050905080821061515f57808203905090506103c0526101c06103a051600381101561515f5760200201516103e0525b6102e06103a051600381101561515f57602002018051610140610400525b61040051516020610400510161040052610400610400511015614f9457614f72565b6103e05161042052610340516104405261036051610460526103805161048052610480516104605161044051610420516006580161359f565b6104e0526103e0610400525b610400515260206104005103610400526101406104005110614ffa57614fd9565b6104e0516103c05180820282158284830414171561515f57809050905090506402540be4008082049050905080821061515f57808203905090508152505b8151600101808352811415614e2b575b50506102e061016051600381101561515f5760200201516101406103c0525b6103c0515160206103c051016103c0526103c06103c051101561508957615067565b6101a0516103e05261016051610400526102e05161042052610300516104405261032051610460526102a0516104805261048051610460516104405161042051610400516103e051600658016147c3565b6104e0526103a06103c0525b6103c0515260206103c051036103c0526101406103c05110615107576150e6565b6104e05180821061515f57808203905090506103a0526103a051600180821061515f578082039050905061022061016051600381101561515f57602002015180801561515f5782049050905060005260005161018051565b600080fd5b61032b61548f0361032b60003961032b61548f036000f35b600080fd00000000000000000000000007e6332dd090d287d3489245038daf987955dcfb000000000000000000000000e578c856933d8e1082740bf7661e379aa2a30b26000000000000000000000000940f41f0ec9ba1a34cf001cc03347ac092f5f6b50000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75000000000000000000000000049d68029688eabf473097a2fc38ef61633a3c7a000000000000000000000000d02a30d33153877bc20e5721ee53dedee0422b2f00000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000012a05f20000000000000000000000000000000000000000000000000000000004a817c800
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000007e6332dd090d287d3489245038daf987955dcfb000000000000000000000000e578c856933d8e1082740bf7661e379aa2a30b26000000000000000000000000940f41f0ec9ba1a34cf001cc03347ac092f5f6b50000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75000000000000000000000000049d68029688eabf473097a2fc38ef61633a3c7a000000000000000000000000d02a30d33153877bc20e5721ee53dedee0422b2f00000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000003d0900000000000000000000000000000000000000000000000000000000012a05f20000000000000000000000000000000000000000000000000000000004a817c800
-----Decoded View---------------
Arg [0] : _coins (address[3]): 0x07e6332dd090d287d3489245038daf987955dcfb,0xe578c856933d8e1082740bf7661e379aa2a30b26,0x940f41f0ec9ba1a34cf001cc03347ac092f5f6b5
Arg [1] : _underlying_coins (address[3]): 0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e,0x04068da6c83afcfa0e13ba15a6696662335d5b75,0x049d68029688eabf473097a2fc38ef61633a3c7a
Arg [2] : _pool_token (address): 0xd02a30d33153877bc20e5721ee53dedee0422b2f
Arg [3] : _A (uint256): 500
Arg [4] : _fee (uint256): 4000000
Arg [5] : _admin_fee (uint256): 5000000000
Arg [6] : _offpeg_fee_multiplier (uint256): 20000000000
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 00000000000000000000000007e6332dd090d287d3489245038daf987955dcfb
Arg [1] : 000000000000000000000000e578c856933d8e1082740bf7661e379aa2a30b26
Arg [2] : 000000000000000000000000940f41f0ec9ba1a34cf001cc03347ac092f5f6b5
Arg [3] : 0000000000000000000000008d11ec38a3eb5e956b052f67da8bdc9bef8abf3e
Arg [4] : 00000000000000000000000004068da6c83afcfa0e13ba15a6696662335d5b75
Arg [5] : 000000000000000000000000049d68029688eabf473097a2fc38ef61633a3c7a
Arg [6] : 000000000000000000000000d02a30d33153877bc20e5721ee53dedee0422b2f
Arg [7] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [8] : 00000000000000000000000000000000000000000000000000000000003d0900
Arg [9] : 000000000000000000000000000000000000000000000000000000012a05f200
Arg [10] : 00000000000000000000000000000000000000000000000000000004a817c800
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Validator ID :
0 FTM
Amount Staked
0
Amount Delegated
0
Staking Total
0
Staking Start Epoch
0
Staking Start Time
0
Proof of Importance
0
Origination Score
0
Validation Score
0
Active
0
Online
0
Downtime
0 s
Address | Amount | claimed Rewards | Created On Epoch | Created On |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.