Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
Overview
Max Total Supply
1.47364598600218374 aPT-ezETH
Holders
2
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
1.4610272211142723 aPT-ezETHValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xBe687E1f...a04B8ae29 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Adapter.FI Multi-Vault
Compiler Version
vyper:0.3.10
Contract Source Code (Vyper language format)
#pragma version 0.3.10 #pragma optimize codesize #pragma evm-version cancun """ @title Adapter.FI Multi-Vault @license Copyright 2023, 2024 Biggest Lab Co Ltd, Benjamin Scherrey, Sajal Kayan, and Eike Caldeweyher @author BiggestLab (https://biggestlab.io) Benjamin Scherrey, Sajal Kayan """ from vyper.interfaces import ERC20 from vyper.interfaces import ERC4626 implements: ERC20 # BDM HACK! We have some additional optional parameters that it doesn't like. # implements: ERC4626 interface IAdapter: def maxWithdraw() -> uint256: view def maxDeposit() -> uint256: view def totalAssets() -> uint256: view def deposit(asset_amount: uint256, pregen_info: Bytes[4096]=empty(Bytes[4096])): payable def withdraw(asset_amount: uint256 , withdraw_to: address, pregen_info: Bytes[4096]=empty(Bytes[4096])) -> uint256 : payable def claimRewards(claimant: address): payable def managed_tokens() -> DynArray[address, 10]: view interface FundsAllocator: def getTargetBalances(_vault_balance: uint256, _d4626_asset_target: uint256, _total_assets: uint256, _total_ratios: uint256, _adapter_balances: BalanceAdapter[MAX_ADAPTERS], _min_outgoing_tx: uint256, _withdraw_only: bool) -> (uint256, int256, uint256, BalanceAdapter[MAX_ADAPTERS], address[MAX_ADAPTERS]): pure def getBalanceTxs(_vault_balance: uint256, _target_asset_balance: uint256, _min_proposer_payout: uint256, _total_assets: uint256, _total_ratios: uint256, _adapter_states: BalanceAdapter[MAX_ADAPTERS], _withdraw_only: bool) -> (BalanceTX[MAX_ADAPTERS], address[MAX_ADAPTERS]): pure # Number of potential lenging platform adapters. MAX_ADAPTERS : constant(uint256) = 5 MAX_SLIPPAGE_PERCENT : immutable(decimal) # Contract owner hold 2% of the yield. YIELD_FEE_PERCENTAGE : constant(uint256) = 2 # 0% of the yield belongs to the Strategy proposer. PROPOSER_FEE_PERCENTAGE: constant(uint256) = 0 # For use in support of _claim_fees enum FeeType: BOTH YIELDS PROPOSER # ERC-20 attributes for this Vault's share token. name: public(immutable(String[64])) symbol: public(immutable(String[32])) decimals: public(immutable(uint8)) asset: public(immutable(address)) # Controlling & Governance DAOs/Wallets owner: public(address) governance: public(address) funds_allocator: public(address) adapters : public(DynArray[address, MAX_ADAPTERS]) managed_tokens: HashMap[address, address] #mapping between token to adapter vault_asset_balance_cache: transient(uint256) adapters_asset_balance_cache: transient(HashMap[address, uint256]) total_asset_balance_cache: transient(uint256) # Strategy Management current_proposer: public(address) min_proposer_payout: public(uint256) struct AdapterValue: ratio: uint256 last_asset_value: uint256 strategy: public(HashMap[address, AdapterValue]) # Summary Financial History of the Vault total_assets_deposited: public(uint256) total_assets_withdrawn: public(uint256) total_yield_fees_claimed: public(uint256) total_strategy_fees_claimed: public(uint256) # ERC20 Representation of Vault Shares totalSupply: public(uint256) balanceOf: public(HashMap[address, uint256]) allowance: public(HashMap[address, HashMap[address, uint256]]) event AdapterAdded: sender: indexed(address) adapter_addr: indexed(address) event AdapterRemoved: sender: indexed(address) afapter_addr: indexed(address) final_balance: uint256 forced: bool event Transfer: sender: indexed(address) receiver: indexed(address) value: uint256 event Approval: owner: indexed(address) spender: indexed(address) value: uint256 event Deposit: sender: indexed(address) owner: indexed(address) assets: uint256 shares: uint256 event SlippageDeposit: sender: indexed(address) owner: indexed(address) assets: uint256 desired_shares: uint256 actual_shares: uint256 event Withdraw: sender: indexed(address) receiver: indexed(address) owner: indexed(address) assets: uint256 shares: uint256 event SlippageWithdraw: sender: indexed(address) receiver: indexed(address) owner: indexed(address) assets: uint256 shares: uint256 actual_assets : uint256 struct AdapterStrategy: adapter: address ratio: uint256 event StrategyActivation: strategy: AdapterStrategy[MAX_ADAPTERS] proposer: address event AdapterLoss: adapter: indexed(address) last_value: uint256 current_value: uint256 event GovernanceChanged: new_governor: indexed(address) old_governor: indexed(address) event VaultDeployed: name: indexed(String[64]) symbol: indexed(String[32]) decimals: uint8 asset: indexed(address) event FundsAllocatorChanged: new_allocator: indexed(address) old_allocator: indexed(address) event OwnerChanged: new_owner: indexed(address) old_owner: indexed(address) @external def __init__(_name: String[64], _symbol: String[32], _decimals: uint8, _erc20asset : address, _governance: address, _funds_allocator: address, _max_slippage_percent: decimal): """ @notice Constructor for 4626 contract. @param _name of shares token @param _symbol identifier of shares token @param _decimals increment for division of shares token @param _erc20asset : contract address for asset ERC20 token @param _governance contract address @param _funds_allocator contract address @param _max_slippage_percent default maximum acceptable slippage for deposits/withdraws as a percentage """ # BDM - had to remove these two assertions so the code size would be small enough to deploy. #assert _governance != empty(address), "Governance cannot be null address." #assert _funds_allocator != empty(address), "Fund allocator cannot be null address." MAX_SLIPPAGE_PERCENT = _max_slippage_percent name = _name symbol = _symbol decimals = _decimals asset = _erc20asset self.owner = msg.sender self.governance = _governance self.funds_allocator = _funds_allocator self.totalSupply = 0 log VaultDeployed(_name, _symbol, _decimals, _erc20asset) log OwnerChanged(msg.sender, empty(address)) log GovernanceChanged(_governance, empty(address)) log FundsAllocatorChanged(_funds_allocator, empty(address)) @external def replaceOwner(_new_owner: address) -> bool: """ @notice replace the current 4626 owner with a new one. @param _new_owner address of the new contract owner @return True, if contract owner was replaced, False otherwise """ assert msg.sender == self.owner, "Only existing owner can replace the owner." assert _new_owner != empty(address), "Owner cannot be null address." log OwnerChanged(_new_owner, self.owner) self.owner = _new_owner return True @external def replaceGovernanceContract(_new_governance: address) -> bool: """ @notice replace the current Governance contract with a new one. @param _new_governance address of the new governance contract @return True, if governance contract was replaced, False otherwise """ assert msg.sender == self.governance, "Only existing Governance contract may replace itself." assert _new_governance != empty(address), "Governance cannot be null address." log GovernanceChanged(_new_governance, self.governance) self.governance = _new_governance return True @external def replaceFundsAllocator(_new_funds_allocator: address) -> bool: """ @notice replace the current funds allocator contract with a new one. @param _new_funds_allocator address of the new contract @return True, if funds allocator contract was replaced, False otherwise """ assert msg.sender == self.owner, "Only owner can change the funds allocation contract!" assert _new_funds_allocator != empty(address), "FundsAllocator cannot be null address." log FundsAllocatorChanged(_new_funds_allocator, self.funds_allocator) self.funds_allocator = _new_funds_allocator return True # Can't simply have a public adapters variable due to this Vyper issue: # https://github.com/vyperlang/vyper/issues/2897 @view @external def adapter_list() -> DynArray[address, MAX_ADAPTERS]: """ @notice convenience function returning list of adapters @return list of lending adapter addresses """ return self.adapters @internal def _set_strategy(_proposer: address, _strategies : AdapterStrategy[MAX_ADAPTERS], _min_proposer_payout : uint256, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]) -> bool: assert msg.sender == self.governance, "Only Governance DAO may set a new strategy." assert _proposer != empty(address), "Proposer can't be null address." # Are we replacing the old proposer? if self.current_proposer != _proposer: current_assets : uint256 = self._totalAssetsNoCache() # self._totalAssetsCached() # Is there enough payout to actually do a transaction? yield_fees : uint256 = 0 strat_fees : uint256 = 0 yield_fees, strat_fees = self._claimable_fees_available(current_assets) if strat_fees > self.min_proposer_payout: # Pay prior proposer his earned fees. self._claim_fees(FeeType.PROPOSER, 0, pregen_info, current_assets) self.current_proposer = _proposer self.min_proposer_payout = _min_proposer_payout # Clear out all existing ratio allocations. for adapter in self.adapters: self.strategy[adapter].ratio = 0 # Now set strategies according to the new plan. for strategy in _strategies: plan : AdapterValue = empty(AdapterValue) plan.ratio = strategy.ratio plan.last_asset_value = self.strategy[strategy.adapter].last_asset_value self.strategy[strategy.adapter] = plan log StrategyActivation(_strategies, _proposer) return True @external def set_strategy(_proposer: address, _strategies : AdapterStrategy[MAX_ADAPTERS], _min_proposer_payout : uint256, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> bool: """ @notice establishes new strategy of adapter ratios and minumum value of automatic txs into adapters @param _proposer address of wallet who proposed strategy and will be entitled to fees during its activation @param _strategies list of ratios for each adapter for funds allocation @param _min_proposer_payout for automated txs into adapters or automatic payout of fees to proposer upon activation of new strategy @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return True if strategy was activated, False overwise """ applied: bool = self._set_strategy(_proposer, _strategies, _min_proposer_payout, pregen_info) self._dirtyAssetCache() return applied @internal def _add_adapter(_adapter: address) -> bool: # Is this from the owner? assert msg.sender == self.owner, "Only owner can add new Lending Adapters." # Do we already support this adapter? assert (_adapter in self.adapters) == False, "adapter already supported." # Is this likely to be an actual IAdapter contract? # BDM - for some reason this raw_call blows up the contract size! #response: Bytes[32] = empty(Bytes[32]) #result_ok: bool = empty(bool) #result_ok, response = raw_call(_adapter, method_id("maxDeposit()"), max_outsize=32, is_static_call=True, revert_on_failure=False) #assert (response != empty(Bytes[32])), "Doesn't appear to be an IAdapter." self.adapters.append(_adapter) self._manage_adapter(_adapter, 0x0000000000000000000000000000000000000000) log AdapterAdded(msg.sender, _adapter) return True @external def add_adapter(_adapter: address) -> bool: """ @notice adds a new Adapter adapter to the 4626 vault. @param _adapter Address for new adapter to evaluate @return True if adapter was added, False otherwise @dev If the current strategy doesn't already have an allocation ratio for this adapter it will receive no funds until a new strategy is activated and a balanceAdapters or deposit/withdraw tx is made. """ return self._add_adapter(_adapter) @internal @pure def _defaultSlippage(_desiredAssets: uint256, _minAssets: uint256) -> uint256: min_transfer_balance : uint256 = _minAssets if _minAssets == 0: calc : uint256 = convert(convert(_desiredAssets, decimal) * (MAX_SLIPPAGE_PERCENT/100.0), uint256) min_transfer_balance = _desiredAssets - calc assert _desiredAssets >= min_transfer_balance, "Desired assets cannot be less than minimum assets!" return min_transfer_balance @internal def _slippageAllowedBalance(_assetsToMove: uint256, _minAssetsToMove: uint256) -> uint256: """ Balancing Adapters theoretically should result in zero loss in total assets. Slippage allowances change this so we determine the difference between the targeted funds moved and the allowable minimum funds moved and apply this delta to the total assets controlled by the vault as the minimum remaining total assets controlled by this vault post adapter balancing. If _assetsToMove is zero then we're looking at a deposit and _minAssetsToMove becomes the maximum slippage value. This value should be provided to the _min_tasset_balance of _balanceAdapters requests. """ if _assetsToMove == 0: return self._totalAssetsCached() - _minAssetsToMove _minAssetsToMove = self._defaultSlippage(_assetsToMove, _minAssetsToMove) return self._totalAssetsCached() - (_assetsToMove - _minAssetsToMove) @internal def _remove_adapter(_adapter: address, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS], _rebalance: bool = True, _force: bool = False, _min_assets: uint256 = 0) -> bool: # Is this from the owner? assert msg.sender == self.owner, "Only owner can remove Lending Adapters." if _adapter not in self.adapters: return False # Determine acceptable slippage. adapter_assets : uint256 = self._adapterAssets(_adapter) min_transfer_balance : uint256 = self._defaultSlippage(adapter_assets, _min_assets) max_loss : uint256 = adapter_assets - min_transfer_balance # Clear out any strategy ratio this adapter may have. self.strategy[_adapter].ratio = 0 if _rebalance == True: initialVaultAssets : uint256 = self._totalAssetsCached() self._balanceAdapters(0, max_loss, pregen_info, False) if not _force: afterVaultAssets : uint256 = self._totalAssetsCached() if afterVaultAssets < initialVaultAssets: # We've taken some loss across the balancing transactions. loss : uint256 = initialVaultAssets - afterVaultAssets assert adapter_assets >= loss, "ERROR - loss was greater than adapter assets. Try to remove without rebalancing." assert max_loss >= loss, "ERROR - too much slippage removing adapter. Try to remove without rebalancing." else: if adapter_assets > 0: assets_withdrawn : uint256 = self._adapter_withdraw(_adapter, adapter_assets, self, pregen_info, _force) if not _force: # If force semantics was chosen it means the contract owner is willing to leave any assets # behind in this adapter because it isn't behaving properly and we urgently need it gone. assert self._adapterAssets(_adapter) == 0, "ERROR - adapter adapter to be removed still has assets!" assert min_transfer_balance <= assets_withdrawn, "ERROR - too much slippage on adapter withdraw." # Walk over the list of adapters and get rid of this one. new_adapters : DynArray[address, MAX_ADAPTERS] = empty(DynArray[address, MAX_ADAPTERS]) for adapter in self.adapters: if adapter != _adapter: new_adapters.append(adapter) self.adapters = new_adapters #UnLock adapter's tokens self._manage_adapter(0x0000000000000000000000000000000000000000, _adapter) log AdapterRemoved(msg.sender, _adapter, self._adapterAssets(_adapter), _force) return True @external def remove_adapter(_adapter: address, _rebalance: bool = True, _force: bool = False, _min_assets: uint256 = 0, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> bool: """ @notice removes Adapter adapter from the 4626 vault. @param _adapter address to be removed @param _rebalance if True will empty adapter before removal. @param _force causes adapter to be removed despite any slippage. @param _min_assets the minimum amount of assets that should be recovered from the adapter. @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return True if adapter was removed, False otherwise """ return self._remove_adapter(_adapter, pregen_info, _rebalance, _force, _min_assets) @internal def _swap_adapters(_adapterOld: address, _adapterNew: address, _force: bool = False, _min_assets : uint256 = 0) -> bool: # Is this from the owner? assert msg.sender == self.owner, "Only owner can swap Lending Adapters." assert _adapterOld != empty(address) and _adapterNew != empty(address), "Can't have empty address for adapter." OldAssets : uint256 = self._adapterAssets(_adapterOld) NewAssets : uint256 = self._adapterAssets(_adapterNew) if not _force and OldAssets > 0: # Is there any slippage? if NewAssets < OldAssets: min_transfer_balance : uint256 = self._defaultSlippage(OldAssets, _min_assets) assert min_transfer_balance <= NewAssets, "ERROR - Swap exceeds maximum slippage." # Now find the old adapter and replace with the new one. pos: uint256 = 0 found : bool = False for adapter in self.adapters: if adapter == _adapterOld: found = True break pos += 1 assert found, "Adapter to be replaced was not found." self.adapters[pos] = _adapterNew self.strategy[_adapterNew].ratio = self.strategy[_adapterOld].ratio self.strategy[_adapterNew].last_asset_value = NewAssets self.strategy[_adapterOld] = empty(AdapterValue) #Transfer adapter's tokens locks self._manage_adapter(_adapterNew, _adapterOld) log AdapterRemoved(msg.sender, _adapterOld, self._adapterAssets(_adapterOld), _force) log AdapterAdded(msg.sender, _adapterNew) return True @external def swap_adapters(_adapterOld: address, _adapterNew: address, _force: bool = False, _min_assets : uint256 = 0) -> bool: """ @notice changes swaps address for a adapter. This is the upgrade mechanism for an adapter. @param _adapterOld Address of the current adapter contract @param _adapterNew Address of the replacement adapter contract @param _force if True then complete the swap regardless of slippage. @param _min_assets the minimum amount of assets the replaement contract should report """ return self._swap_adapters(_adapterOld, _adapterNew, _force, _min_assets) @internal def _dirtyAssetCache(_clearVaultBalance : bool = True, _clearAdapters : bool = True, _adapter : address = empty(address)): self.total_asset_balance_cache = 0 if _clearVaultBalance: self.vault_asset_balance_cache = 0 if _clearAdapters: if _adapter == empty(address): # Clear them all for adapter in self.adapters: self.adapters_asset_balance_cache[adapter] = 0 else: self.adapters_asset_balance_cache[_adapter] = 0 @internal def _vaultAssets() -> uint256: if self.vault_asset_balance_cache == 0: self.vault_asset_balance_cache = ERC20(asset).balanceOf(self) self.total_asset_balance_cache = 0 return self.vault_asset_balance_cache @internal def _adapterAssets(_adapter: address) -> uint256: if _adapter == empty(address): return 0 result : uint256 = self.adapters_asset_balance_cache[_adapter] if result != 0: return result result = IAdapter(_adapter).totalAssets() self.adapters_asset_balance_cache[_adapter] = result self.total_asset_balance_cache = 0 return result @internal def _totalAssetsCached() -> uint256: if self.total_asset_balance_cache > 0: return self.total_asset_balance_cache assetqty : uint256 = self._vaultAssets() for adapter in self.adapters: assetqty += self._adapterAssets(adapter) self.total_asset_balance_cache = assetqty return assetqty @external def totalAssetsCached() -> uint256: return self._totalAssetsCached() @internal @view def _totalAssetsNoCache() -> uint256: assetqty : uint256 = ERC20(asset).balanceOf(self) for adapter in self.adapters: assetqty += IAdapter(adapter).totalAssets() return assetqty @external @view def totalAssets() -> uint256: """ @notice returns current total asset value for 4626 vault & all its attached Adapter adapters. @return sum of assets """ return self._totalAssetsNoCache() @internal @view def _totalReturns(_current_assets : uint256) -> int256: # Avoid having to call _totalAssets if we already know the value. current_holdings : uint256 = _current_assets if current_holdings == 0: current_holdings = self._totalAssetsNoCache() total_returns: int256 = convert(self.total_assets_withdrawn + \ current_holdings + \ self.total_yield_fees_claimed + \ self.total_strategy_fees_claimed, int256) - \ convert(self.total_assets_deposited, int256) return total_returns @external @view def totalReturns() -> int256: """ @notice computes current profits (denominated in assets) available under control of this 4626 vault. @return total assets held by adapter above what is currently deposited. @dev This includes the fees owed to 4626 contract owner and current strategy proposer. """ assets : uint256 = self._totalAssetsNoCache() return self._totalReturns(assets) @internal @view def _claimable_fees_available(_current_assets : uint256 = 0) -> (uint256, uint256): """ Returns yield fees, strategy fees available. """ total_assets : uint256 = _current_assets # Only call _totalAssets() if it wasn't passed in. if total_assets == 0: total_assets = self._totalAssetsNoCache() total_returns : int256 = self._totalReturns(total_assets) if total_returns <= 0: return 0, 0 yield_fees_available: uint256 = 0 strategy_fees_available : uint256 = 0 total_yield_ever : uint256 = (convert(total_returns,uint256) * YIELD_FEE_PERCENTAGE) / 100 total_strat_fees_ever : uint256 = (convert(total_returns,uint256) * PROPOSER_FEE_PERCENTAGE) / 100 if self.total_yield_fees_claimed < total_yield_ever: yield_fees_available = total_yield_ever - self.total_yield_fees_claimed if self.total_strategy_fees_claimed < total_strat_fees_ever: strategy_fees_available = total_strat_fees_ever - self.total_strategy_fees_claimed return yield_fees_available, strategy_fees_available @external @view def claimable_yield_fees_available(_current_assets : uint256 = 0) -> uint256: """ @notice determines total yields aailable for 4626 vault owner. @param _current_assets optional parameter if current total assets is already known. @return total assets contract owner could withdraw now in fees. """ yield_fees : uint256 = 0 strategy_fees: uint256 = 0 yield_fees, strategy_fees = self._claimable_fees_available(_current_assets) return yield_fees @external @view def claimable_strategy_fees_available(_current_assets : uint256 = 0) -> uint256: """ @notice determines total yields aailable for current strategy proposer. @param _current_assets optional parameter if current total assets is already known. @return total assets strategy proposer is owed presently. """ yield_fees : uint256 = 0 strategy_fees: uint256 = 0 yield_fees, strategy_fees = self._claimable_fees_available(_current_assets) return strategy_fees @external @view def claimable_all_fees_available(_current_assets : uint256 = 0) -> uint256: """ @notice determines total fees owed for both 4626 vault owner & proposer of current strategy. @param _current_assets optional parameter if current total assets is already known. @return Claimable fees available for yield and proposer """ yield_fees : uint256 = 0 strategy_fees: uint256 = 0 yield_fees, strategy_fees = self._claimable_fees_available(_current_assets) return yield_fees + strategy_fees @internal def _claimable_fees_by_me(_yield : FeeType, _asset_amount: uint256, _current_assets: uint256) -> (uint256, uint256): yield_fees : uint256 = 0 strat_fees : uint256 = 0 yield_fees, strat_fees = self._claimable_fees_available(_current_assets) # Only yields, no strategy. if _yield == FeeType.YIELDS: strat_fees = 0 # Only strategy, no yields. if _yield == FeeType.PROPOSER: yield_fees = 0 # If current proposer is zero address then we won't pay yield fees. if self.current_proposer == empty(address): yield_fees = 0 # Only owner may claim yield fees. if (_yield == FeeType.YIELDS or _yield == FeeType.BOTH) and msg.sender != self.owner: yield_fees = 0 # Only current proposer or governance may claim strategy fees. if _yield == FeeType.PROPOSER or _yield == FeeType.BOTH: assert msg.sender == self.current_proposer or msg.sender == self.governance, "Only curent proposer or governance may claim strategy fees." # Do we have enough fees to pay out the request? If so how much should we extract? assert _asset_amount <= yield_fees + strat_fees, "Not enough fees to fulfill requested amount." return yield_fees, strat_fees @internal def _claim_fees(_yield : FeeType, _asset_amount: uint256, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS], _current_assets : uint256 = 0, _min_assets: uint256 = 0) -> uint256: yield_fees : uint256 = 0 strat_fees : uint256 = 0 yield_fees, strat_fees = self._claimable_fees_by_me(_yield, _asset_amount, _current_assets) fees_to_claim : uint256 = yield_fees + strat_fees if _asset_amount > 0: # Otherwise we take it all. fees_to_claim = _asset_amount # This will be lower than or equal to the total available fees. # Do we have enough balance locally to satisfy the claim? current_vault_assets : uint256 = self._vaultAssets() if current_vault_assets < fees_to_claim: # Need to liquidate some shares to fulfill. Insist on withdraw only semantics. # Note - there is a chance that balance adapters could return more than we asked for so # don't just give it all away in case there's an overage. fees_to_claim = min(self._balanceAdapters(fees_to_claim, _min_assets, pregen_info, True), fees_to_claim) else: fees_to_claim = min(fees_to_claim, current_vault_assets) # Adjust fees proportionally to account for slippage. if strat_fees > 0 and yield_fees > 0: strat_fees = convert((convert(strat_fees, decimal)/convert(strat_fees+yield_fees, decimal))*convert(fees_to_claim, decimal), uint256) yield_fees = fees_to_claim - strat_fees elif strat_fees > 0: strat_fees = fees_to_claim else: yield_fees = fees_to_claim # Update our global payout records. self.total_yield_fees_claimed += yield_fees self.total_strategy_fees_claimed += strat_fees # Do we have something independent for the strategy proposer? if strat_fees > 0 and self.owner != self.current_proposer: # We only pay out if the amount is high enough, otherwise the vault keeps it. # Unless the person requesting the payout is the current proposer then he must # want it anyway. if msg.sender == self.current_proposer or strat_fees >= self.min_proposer_payout: ERC20(asset).transfer(self.current_proposer, strat_fees, default_return_value=True) strat_fees = 0 # Is there anything left over to transfer for Yield? (Which might also include strat) if yield_fees + strat_fees > 0: ERC20(asset).transfer(self.owner, yield_fees + strat_fees, default_return_value=True) # Clear all caches! self._dirtyAssetCache() return fees_to_claim @external def claim_yield_fees(_asset_request: uint256 = 0, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> uint256: """ @notice used by 4626 vault owner to withdraw fees. @param _asset_request total assets desired for withdrawl. @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return total assets transferred. @dev If _asset_request is 0 then will withdrawl all eligible assets. """ return self._claim_fees(FeeType.YIELDS, _asset_request, pregen_info) @external def claim_strategy_fees(_asset_request: uint256 = 0, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> uint256: """ @notice user by current Strategy proposer to withdraw fees. @param _asset_request total assets desired for withdrawl. @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return total assets transferred. @dev If _asset_request is 0 then will withdrawl all eligible assets. """ return self._claim_fees(FeeType.PROPOSER, _asset_request, pregen_info) @external def claim_all_fees(_asset_request: uint256 = 0, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> uint256: """ @notice if 4626 vault owner and Strategy proposer are same wallet address, used to withdraw all fees at once. @param _asset_request total assets desired for withdrawl. @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return total assets transferred. @dev If _asset_request is 0 then will withdrawl all eligible assets. """ return self._claim_fees(FeeType.BOTH, _asset_request, pregen_info) @internal @view def _convertToShares(_asset_amount: uint256, _starting_assets: uint256) -> uint256: shareqty : uint256 = self.totalSupply yield_fees : uint256 = 0 strat_fees : uint256 = 0 yield_fees, strat_fees = self._claimable_fees_available(_starting_assets) claimable_fees : uint256 = yield_fees + strat_fees # If there aren't any shares/assets yet it's going to be 1:1. if shareqty == 0 : return _asset_amount if _starting_assets == 0 : return _asset_amount # Less fees assert _starting_assets >= claimable_fees, "_convertToShares sanity failure!" # BDM assetqty : uint256 = _starting_assets - claimable_fees return _asset_amount * shareqty / assetqty @external @view def convertToShares(_asset_amount: uint256) -> uint256: """ @notice calculates the current number of 4626 shares would be received for a deposit of assets. @param _asset_amount the quantity of assets to be converted to shares. @return current share value for the asset quantity @dev any fees owed to 4626 owner or strategy proposer are removed before conversion. """ return self._convertToShares(_asset_amount, self._totalAssetsNoCache()) @internal @view def _convertToAssets(_share_amount: uint256, _starting_assets: uint256) -> uint256: shareqty : uint256 = self.totalSupply yield_fees : uint256 = 0 strat_fees : uint256 = 0 yield_fees, strat_fees = self._claimable_fees_available(_starting_assets) claimable_fees : uint256 = yield_fees + strat_fees # Less fees assert _starting_assets >= claimable_fees, "_convertToAssets sanity failure!" # BDM # If there aren't any shares yet it's going to be 1:1. if shareqty == 0: return _share_amount if _starting_assets - claimable_fees == 0 : return _share_amount return _share_amount * (_starting_assets - claimable_fees) / shareqty @external @view def convertToAssets(_share_amount: uint256) -> uint256: """ @notice calculates the current quantity of assets would be received for a deposit of 4626 shares. @param _share_amount the quantity of 4626 shares to be converted to assets. @return current asset value for the share quantity @dev any fees owed to 4626 owner or strategy proposer are removed before conversion. """ return self._convertToAssets(_share_amount, self._totalAssetsNoCache()) @external @view def maxDeposit(_spender: address) -> uint256: """ @notice Maximum amount of the underlying asset that can be deposited into the Vault for the receiver, through a deposit call. @param _spender address (ignored) @return a really big number that we'll never hit. @dev Due to the nature of the LPs that we depend upon there's no way to properly support this part of the EIP-4626 spec. """ return convert(max_value(int128), uint256) @external @view def previewDeposit(_asset_amount: uint256) -> uint256: """ @notice This function converts asset amount to shares in deposit @param _asset_amount Number amount of assets to evaluate @return Shares per asset amount in deposit """ return self._convertToShares(_asset_amount, self._totalAssetsNoCache()) @external @view def maxMint(_receiver: address) -> uint256: """ @notice Maximum amount of shares that can be minted from the Vault for the receiver, through a mint call. @param _receiver address (ignored) @return a really big number that we'll never hit. @dev Due to the nature of the LPs that we depend upon there's no way to properly support this part of the EIP-4626 spec. """ return convert(max_value(int128), uint256) @external @view def previewMint(_share_amount: uint256) -> uint256: """ @notice This function returns asset qty that would be returned for this share_amount per mint @param _share_amount Number amount of shares to evaluate @return Assets per share amount in mint """ return self._convertToAssets(_share_amount, self._totalAssetsNoCache()) @external def mint(_share_amount: uint256, _receiver: address, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS] = empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> uint256: """ @notice This function mints asset qty that would be returned for this share_amount to receiver @param _share_amount Number amount of shares to evaluate @param _receiver Address of receiver to evaluate @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return Asset value of _share_amount """ assetqty : uint256 = self._convertToAssets(_share_amount, self._totalAssetsCached()) shares : uint256 = 0 assets : uint256 = 0 shares, assets = self._deposit(assetqty, _receiver, 0, pregen_info) self._dirtyAssetCache() return assets @external @view def maxWithdraw(_owner: address) -> uint256: """ @notice This function returns maximum assets this _owner can extract @param _owner Address of owner of assets to evaluate @return maximum assets this _owner can withdraw """ return self._convertToAssets(self.balanceOf[_owner], self._totalAssetsNoCache()) @external @view def previewWithdraw(_asset_amount: uint256) -> uint256: """ @notice This function returns asset qty per share amount for withdraw @param _asset_amount Number amount of assets to evaluate @return Share qty per asset amount in withdraw """ return self._convertToShares(_asset_amount, self._totalAssetsNoCache()) @external @view # Returns maximum shares this _owner can redeem. def maxRedeem(_owner: address) -> uint256: """ @notice This function returns maximum shares this _owner can redeem @param _owner Address of owner of assets to evaluate @return maximum shares this _owner can redeem """ return self.balanceOf[_owner] @external @view def previewRedeem(_share_amount: uint256) -> uint256: """ @notice This function returns asset qty per share amount for redemption @param _share_amount Number amount of shares to evaluate @return asset qty per share amount in redemption """ return self._convertToAssets(_share_amount, self._totalAssetsNoCache()) @external def redeem(_share_amount: uint256, _receiver: address, _owner: address, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> uint256: """ @notice This function redeems asset qty that would be returned for this share_amount to receiver from owner @param _share_amount Number amount of shares to evaluate @param _receiver Address of receiver to evaluate @param _owner Address of owner of assets to evaluate @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return Asset qty withdrawn """ assetqty: uint256 = self._convertToAssets(_share_amount, self._totalAssetsCached()) # NOTE - this is accepting the MAX_SLIPPAGE_PERCENT % slippage default. shares : uint256 = 0 assets : uint256 = 0 shares, assets = self._withdraw(assetqty, _receiver, _owner, 0, pregen_info) self._dirtyAssetCache() return assets # This structure must match definition in Funds Allocator contract. struct BalanceTX: qty: int256 adapter: address # This structure must match definition in Funds Allocator contract. struct BalanceAdapter: adapter: address current: uint256 last_value: uint256 max_deposit: int256 max_withdraw: int256 # represented as a negative number ratio: uint256 target: uint256 delta: int256 @internal @view def _getAdapterMaxWithdraw(_adapter: address) -> int256: """ @dev Given an adapter's address return the maximum withdraw amount allowed for that adapter. """ # If the value is higher than what can be represented by an int256 # make it the maximum value possible with an int256. _umax : uint256 = IAdapter(_adapter).maxWithdraw() if _umax > convert(max_value(int256), uint256): _umax = convert(max_value(int256), uint256) return convert(_umax, int256) * -1 @internal @view def _getAdapterMaxDeposit(_adapter: address) -> int256: """ @dev Given an adapter's address return the maximum deposit amount allowed for that adapter. This will be a negative number. """ # If the value is higher than what can be represented by an int256 # make it the maximum value possible with an int256. _umax : uint256 = IAdapter(_adapter).maxDeposit() if _umax > convert(max_value(int256), uint256): return max_value(int256) return convert(_umax, int256) # Returns current 4626 asset balance, first 3 parts of BalanceAdapters, total Assets, & total ratios of Strategy. @internal def _getCurrentBalances() -> (uint256, BalanceAdapter[MAX_ADAPTERS], uint256, uint256): current_local_asset_balance : uint256 = self._vaultAssets() adapter_balances: BalanceAdapter[MAX_ADAPTERS] = empty(BalanceAdapter[MAX_ADAPTERS]) # If there are no adapters then nothing to do. if len(self.adapters) == 0: return current_local_asset_balance, adapter_balances, current_local_asset_balance, 0 total_balance: uint256 = current_local_asset_balance total_ratios: uint256 = 0 pos: uint256 = 0 for adapter in self.adapters: adapter_balances[pos].adapter = adapter adapter_balances[pos].current = self._adapterAssets(adapter) total_balance += adapter_balances[pos].current adapter_balances[pos].max_withdraw = self._getAdapterMaxWithdraw(adapter) adapter_balances[pos].max_deposit = self._getAdapterMaxDeposit(adapter) plan : AdapterValue = self.strategy[adapter] adapter_balances[pos].ratio = plan.ratio total_ratios += plan.ratio adapter_balances[pos].last_value = plan.last_asset_value pos += 1 return current_local_asset_balance, adapter_balances, total_balance, total_ratios @external def getCurrentBalances() -> (uint256, BalanceAdapter[MAX_ADAPTERS], uint256, uint256): """ @notice This function returns current balances of adapters @return Current balances of adapters """ current_local_asset_balance: uint256 = 0 adapter_balances: BalanceAdapter[MAX_ADAPTERS] = empty(BalanceAdapter[MAX_ADAPTERS]) total_balance: uint256 = 0 total_ratios: uint256 = 0 current_local_asset_balance, adapter_balances, total_balance, total_ratios = self._getCurrentBalances() self._dirtyAssetCache() return current_local_asset_balance, adapter_balances, total_balance, total_ratios @internal @view def _getBalanceTxs(_target_asset_balance: uint256, _min_proposer_payout: uint256, _total_assets: uint256, _total_ratios: uint256, _adapter_states: BalanceAdapter[MAX_ADAPTERS], _withdraw_only : bool) -> (BalanceTX[MAX_ADAPTERS], address[MAX_ADAPTERS]): current_local_asset_balance : uint256 = ERC20(asset).balanceOf(self) return FundsAllocator(self.funds_allocator).getBalanceTxs(current_local_asset_balance, _target_asset_balance, _min_proposer_payout, _total_assets, _total_ratios, _adapter_states, _withdraw_only) @internal def _balanceAdapters(_target_asset_balance: uint256, _min_target_asset_balance: uint256, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS], _withdraw_only : bool ) -> uint256: # If _target_asset_balance is zero then we're looking at a deposit and _min_target_asset_balance # becomes the maximum slippage value (via _slippageAllowedBalance). # Make sure we have enough assets to send to _receiver. txs: BalanceTX[MAX_ADAPTERS] = empty(BalanceTX[MAX_ADAPTERS]) blocked_adapters: address[MAX_ADAPTERS] = empty(address[MAX_ADAPTERS]) min_total_asset_balance : uint256 = self._slippageAllowedBalance(_target_asset_balance, _min_target_asset_balance) # If there are no adapters then nothing to do. if len(self.adapters) == 0: return ERC20(asset).balanceOf(self) # Setup current state of vault & adapters & strategy. d4626_assets: uint256 = 0 adapter_states: BalanceAdapter[MAX_ADAPTERS] = empty(BalanceAdapter[MAX_ADAPTERS]) total_assets: uint256 = 0 total_ratios: uint256 = 0 d4626_assets, adapter_states, total_assets, total_ratios = self._getCurrentBalances() txs, blocked_adapters = self._getBalanceTxs(_target_asset_balance, self.min_proposer_payout, total_assets, total_ratios, adapter_states, _withdraw_only) # If there are blocked_adapters then set their strategy ratios to zero. for adapter in blocked_adapters: if adapter == empty(address): break new_strat : AdapterValue = self.strategy[adapter] new_strat.ratio = 0 self.strategy[adapter] = new_strat new_strat_asset_value : uint256 = self._adapterAssets(adapter) # Adjust minimum acceptable balances downwards because this is not a slippage loss. min_total_asset_balance -= (new_strat.last_asset_value - new_strat_asset_value) log AdapterLoss(adapter, new_strat.last_asset_value, new_strat_asset_value) # Move the funds in/out of Lending Adapters as required. for dtx in txs: if dtx.adapter == empty(address): break if dtx.qty == 0: continue # If the outgoing tx is larger than the min_proposer_payout then do it, otherwise ignore it. if dtx.qty >= convert(self.min_proposer_payout, int256): # Move funds into the lending adapter's adapter. # It's possible due to slippage we may not have enough assets in the vault to # fulfill the entire deposit transfer. deposit_qty : uint256 = min(convert(dtx.qty, uint256), self._vaultAssets()) self._adapter_deposit(dtx.adapter, deposit_qty, pregen_info) # Negative quanties indicate a withdraw from the adapter into the vault. elif dtx.qty < 0: # Liquidate funds from lending adapter's adapter. qty: uint256 = convert(dtx.qty * -1, uint256) assets_withdrawn : uint256 = self._adapter_withdraw(dtx.adapter, qty, self, pregen_info) final_asset_balance : uint256 = self._totalAssetsCached() assert self._totalAssetsCached() >= min_total_asset_balance, "Slippage exceeded!" return self._vaultAssets() @external def balanceAdapters(_target_asset_balance: uint256, _min_tasset_balance: uint256 = 0, _withdraw_only : bool = False, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> uint256: """ @notice The function provides a way to balance adapters @dev returns the actual balances of assets held in the local vault (not including adapters) after balancing. @param _target_asset_balance Target amount for assets balance in vault (not including adapters). @param _min_tasset_balance Minimum total assets (including adapters) post transaction accounting for slippage. @param _withdraw_only If true no funds will move from vault into adapters during this tx. @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call """ assert msg.sender == self.owner, "only owner can call balanceAdapters" ret: uint256 = self._balanceAdapters(_target_asset_balance, _min_tasset_balance, pregen_info, _withdraw_only) self._dirtyAssetCache() return ret @internal def _mint(_receiver: address, _share_amount: uint256) -> uint256: """ @dev Mint an amount of the token and assigns it to an account. This encapsulates the modification of balances such that the proper events are emitted. @param _to The account that will receive the created tokens. @param _value The amount that will be created. """ assert _receiver != empty(address), "Receiver cannot be zero." self.totalSupply += _share_amount self.balanceOf[_receiver] += _share_amount log Transfer(empty(address), _receiver, _share_amount) return _share_amount @internal @view def _extract_pregen_info(_pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS], _adapter: address) -> Bytes[4096]: #Only extract if pregeninfo len matches lending adapters if len(_pregen_info) == len(self.adapters): #find idx current adapter idx: uint256 = 0 for adapter in self.adapters: if _adapter == adapter: return _pregen_info[idx] idx+=1 return empty(Bytes[4096]) @internal def _adapter_deposit(_adapter: address, _asset_amount: uint256, _pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]): pregen_info: Bytes[4096] = self._extract_pregen_info(_pregen_info, _adapter) response: Bytes[32] = empty(Bytes[32]) starting_assets : uint256 = self._adapterAssets(_adapter) response = raw_call( _adapter, _abi_encode(_asset_amount, pregen_info, method_id=method_id("deposit(uint256,bytes)")), max_outsize=32, is_delegate_call=True, revert_on_failure=True ) # Clear the asset cache for vault and adapter. self._dirtyAssetCache(True, True, _adapter) new_assets : uint256 = self._adapterAssets(_adapter) # Update our last_asset_value in our strategy for protection against LP exploits. self.strategy[_adapter].last_asset_value = new_assets @internal def _adapter_withdraw(_adapter: address, _asset_amount: uint256, _withdraw_to: address, _pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS], _force: bool = False) -> uint256: pregen_info: Bytes[4096] = self._extract_pregen_info(_pregen_info, _adapter) balbefore : uint256 = ERC20(asset).balanceOf(_withdraw_to) response: Bytes[32] = empty(Bytes[32]) result_ok : bool = True assert _adapter != empty(address), "EMPTY ADAPTER!" assert _withdraw_to != empty(address), "EMPTY WITHDRAW_TO!" if _force: # For revert_on_failure = True result_ok, response = raw_call( _adapter, _abi_encode(_asset_amount, _withdraw_to, pregen_info, method_id=method_id("withdraw(uint256,address,bytes)")), max_outsize=32, is_delegate_call=True, revert_on_failure=False ) else: # For revert_on_failure = False response = raw_call( _adapter, _abi_encode(_asset_amount, _withdraw_to, pregen_info, method_id=method_id("withdraw(uint256,address,bytes)")), max_outsize=32, is_delegate_call=True, revert_on_failure=True ) # Clear the asset cache for vault and adapter. self._dirtyAssetCache(True, True, _adapter) balafter : uint256 = ERC20(asset).balanceOf(_withdraw_to) # Update our last_asset_value in our strategy for protection against LP exploits. self.strategy[_adapter].last_asset_value = self._adapterAssets(_adapter) return balafter - balbefore @internal def _deposit(_asset_amount: uint256, _receiver: address, _min_shares : uint256, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]) -> (uint256, uint256): """ returns shares minted, assets taken """ assert _receiver != empty(address), "Cannot send shares to zero address." assert _asset_amount <= ERC20(asset).balanceOf(msg.sender), "4626Deposit insufficient funds." total_starting_assets : uint256 = self._totalAssetsCached() # MUST COMPUTE IDEAL TRANSFER SHARES FIRST! transfer_shares : uint256 = self._convertToShares(_asset_amount, total_starting_assets) if _min_shares > 0: assert transfer_shares >= _min_shares, "Deposit too low to receive minimum shares." else: _min_shares = self._defaultSlippage(transfer_shares, _min_shares) min_share_value : uint256 = self._convertToAssets(_min_shares, total_starting_assets) # Move assets to this contract from caller in one go. ERC20(asset).transferFrom(msg.sender, self, _asset_amount, default_return_value=True) # Clear the asset cache for vault but not adapters. self._dirtyAssetCache(True, False) bal_diff: uint256 = self._balanceAdapters(empty(uint256), _asset_amount - min_share_value, pregen_info, False) total_after_assets : uint256 = self._totalAssetsCached() assert total_after_assets > total_starting_assets, "ERROR - deposit resulted in loss of assets!" deposit_value : uint256 = total_after_assets-total_starting_assets # We use total_starting_assests to get a quote for the actual shares based on prior rates # as we have not minted any new shares to account for the deposit. real_shares : uint256 = self._convertToShares(deposit_value, total_starting_assets) if real_shares < transfer_shares: assert real_shares >= _min_shares, "ERROR - unable to meet minimum slippage for this deposit!" # We'll transfer what was received. # NOTE - updating transfer_shares means that we are unable to fulfill mint semantics # for a 4626 that has to deal with slippage. The issue is we cannot fix the share # qty because we have no ability to predict the actual asset qty required to get # these shares as it's only AFTER we transfer the assets from the minter/depositer # that we can discover what the adapter with slippage actually credits us with. transfer_shares = real_shares log SlippageDeposit(msg.sender, _receiver, _asset_amount, transfer_shares, transfer_shares) # Now mint assets to return to investor. self._mint(_receiver, transfer_shares) # Update all-time assets deposited for yield tracking. assets_received : uint256 = total_after_assets - total_starting_assets self.total_assets_deposited += assets_received log Deposit(msg.sender, _receiver, assets_received, transfer_shares) return transfer_shares, _asset_amount @external def deposit(_asset_amount: uint256, _receiver: address, _min_shares : uint256 = 0, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> uint256: """ @notice This function provides a way to transfer an asset amount from message sender to receiver @param _asset_amount Number amount of assets to evaluate @param _receiver Address of receiver to evaluate @param _min_shares Minmum number of shares that is acceptable. If 0 then apply MAX_SLIPPAGE_PERCENT % allowable slippage. @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return Share amount deposited to receiver """ shares : uint256 = 0 assets : uint256 = 0 shares, assets = self._deposit(_asset_amount, _receiver, _min_shares, pregen_info) self._dirtyAssetCache() return shares @internal def _withdraw(_asset_amount: uint256, _receiver: address, _owner: address, _min_assets: uint256, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]) -> (uint256, uint256): """ returns shares consumed, assets returned """ # How many shares does it take to get the requested asset amount? # NOTE - it is CRITICAL that shares is fixed immediately before slippage is considered # because we implement redeem in terms of _withdraw. shares: uint256 = self._convertToShares(_asset_amount, self._totalAssetsCached()) # Owner has adequate shares? assert self.balanceOf[_owner] >= shares, "Owner has inadequate shares for this withdraw." # Withdrawl is handled by someone other than the owner? if msg.sender != _owner: assert self.allowance[_owner][msg.sender] >= shares, "Not authorized to move enough owner's shares." self.allowance[_owner][msg.sender] -= shares # Burn the shares. self.balanceOf[_owner] -= shares self.totalSupply -= shares log Transfer(_owner, empty(address), shares) # Make sure we have enough assets to send to _receiver. Do a withdraw only balance. current_balance : uint256 = self._balanceAdapters(_asset_amount, _min_assets, pregen_info, True ) if _asset_amount > current_balance: log SlippageWithdraw(msg.sender, _receiver, _owner, _asset_amount, shares, current_balance) _asset_amount = current_balance # Now send assets to _receiver. ERC20(asset).transfer(_receiver, _asset_amount, default_return_value=True) # Clear the asset cache for vault but not adapters. self._dirtyAssetCache(True, False) # Update all-time assets withdrawn for yield tracking. self.total_assets_withdrawn += _asset_amount log Withdraw(msg.sender, _receiver, _owner, _asset_amount, shares) return (shares, _asset_amount) @external def withdraw(_asset_amount: uint256,_receiver: address,_owner: address, _min_assets: uint256 = 0, pregen_info: DynArray[Bytes[4096], MAX_ADAPTERS]=empty(DynArray[Bytes[4096], MAX_ADAPTERS])) -> uint256: """ @notice This function provides a way to withdraw an asset amount to receiver @param _asset_amount Number amount of assets to evaluate @param _receiver Address of receiver to evaluate @param _owner Address of owner of assets to evaluate @param _min_assets Minimum assets that must be returned (due to slippage) or else reverts. If not specified will be MAX_SLIPPAGE_PERCENT % by default. @param pregen_info Optional list of bytes to be sent to each adapter. These are usually off-chain computed results which optimize the on-chain call @return Share amount withdrawn to receiver """ shares : uint256 = 0 assets : uint256 = 0 shares, assets = self._withdraw(_asset_amount, _receiver, _owner, _min_assets, pregen_info) self._dirtyAssetCache() return shares ### ERC20 functionality. @internal def _transfer(_from: address, _to: address, _value: uint256): assert self.balanceOf[_from] >= _value, "ERC20 transfer insufficient funds." self.balanceOf[_from] -= _value self.balanceOf[_to] += _value log Transfer(_from, _to, _value) @internal def _approve(_owner: address, _spender: address, _value: uint256): self.allowance[_owner][_spender] = _value log Approval(_owner, _spender, _value) @internal def _transferFrom(_operator: address, _from: address, _to:address, _value: uint256): assert self.balanceOf[_from] >= _value, "ERC20 transferFrom insufficient funds." self.balanceOf[_from] -= _value self.balanceOf[_to] += _value assert self.allowance[_from][_operator] >= _value, "ERC20 transfer insufficient allowance." self.allowance[_from][_operator] -= _value log Transfer(_from, _to, _value) @external def transfer(_to : address, _value : uint256) -> bool: """ @dev Transfer token for a specified address @param _to The address to transfer to. @param _value The amount to be transferred. """ self._transfer(msg.sender, _to, _value) return True @external def transferFrom(_from : address, _to : address, _value : uint256) -> bool: """ @dev Transfer tokens from one address to another. @param _from address The address which you want to send tokens from @param _to address The address which you want to transfer to @param _value uint256 the amount of tokens to be transferred """ self._transferFrom(msg.sender, _from, _to, _value) return True @external def approve(_spender : address, _value : uint256) -> bool: """ @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. Beware that changing an allowance with this method brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 @param _spender The address which will spend the funds. @param _value The amount of tokens to be spent. """ self._approve(msg.sender, _spender, _value) return True @external def claimRewards(_adapter: address, reciepent: address): assert msg.sender == self.owner, "Only owner can claimRewards!" assert _adapter in self.adapters, "Not a valid adapter" raw_call( _adapter, _abi_encode(reciepent, method_id=method_id("claimRewards(address)")), max_outsize=0, is_delegate_call=True, revert_on_failure=True ) @internal def _manage_adapter(incoming_adapter: address, outgoing_adapter: address): #If there is an incoming adapter, take an exclusive lock, ensuring nobody (aside from possibly outgoing_adapter) has it locked. if incoming_adapter != 0x0000000000000000000000000000000000000000: #Update managed_tokens, while ensuring unique token lock incoming_handled: DynArray[address, 10] = IAdapter(incoming_adapter).managed_tokens() for token in incoming_handled: old: address = self.managed_tokens[token] assert old==outgoing_adapter, "incoming token already handled" self.managed_tokens[token] = incoming_adapter #In case of adapter removal... ensure all its magaged tokens are either transfered to new adapter or are released if outgoing_adapter != 0x0000000000000000000000000000000000000000: outgoing_handled: DynArray[address, 10] = IAdapter(outgoing_adapter).managed_tokens() for token in outgoing_handled: old: address = self.managed_tokens[token] if incoming_adapter == 0x0000000000000000000000000000000000000000: assert old == outgoing_adapter, "outgoing token already handled" self.managed_tokens[token] = 0x0000000000000000000000000000000000000000 else: #ensures all old adapters tokens have been consumed by the new assert old == incoming_adapter, "outgoing token already handled"
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"name":"AdapterAdded","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"adapter_addr","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"AdapterRemoved","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"afapter_addr","type":"address","indexed":true},{"name":"final_balance","type":"uint256","indexed":false},{"name":"forced","type":"bool","indexed":false}],"anonymous":false,"type":"event"},{"name":"Transfer","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Approval","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Deposit","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"owner","type":"address","indexed":true},{"name":"assets","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"SlippageDeposit","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"owner","type":"address","indexed":true},{"name":"assets","type":"uint256","indexed":false},{"name":"desired_shares","type":"uint256","indexed":false},{"name":"actual_shares","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"Withdraw","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"owner","type":"address","indexed":true},{"name":"assets","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"SlippageWithdraw","inputs":[{"name":"sender","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"owner","type":"address","indexed":true},{"name":"assets","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false},{"name":"actual_assets","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"StrategyActivation","inputs":[{"name":"strategy","type":"tuple[5]","components":[{"name":"adapter","type":"address"},{"name":"ratio","type":"uint256"}],"indexed":false},{"name":"proposer","type":"address","indexed":false}],"anonymous":false,"type":"event"},{"name":"AdapterLoss","inputs":[{"name":"adapter","type":"address","indexed":true},{"name":"last_value","type":"uint256","indexed":false},{"name":"current_value","type":"uint256","indexed":false}],"anonymous":false,"type":"event"},{"name":"GovernanceChanged","inputs":[{"name":"new_governor","type":"address","indexed":true},{"name":"old_governor","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"VaultDeployed","inputs":[{"name":"name","type":"string","indexed":true},{"name":"symbol","type":"string","indexed":true},{"name":"decimals","type":"uint8","indexed":false},{"name":"asset","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"FundsAllocatorChanged","inputs":[{"name":"new_allocator","type":"address","indexed":true},{"name":"old_allocator","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"name":"OwnerChanged","inputs":[{"name":"new_owner","type":"address","indexed":true},{"name":"old_owner","type":"address","indexed":true}],"anonymous":false,"type":"event"},{"stateMutability":"nonpayable","type":"constructor","inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_erc20asset","type":"address"},{"name":"_governance","type":"address"},{"name":"_funds_allocator","type":"address"},{"name":"_max_slippage_percent","type":"fixed168x10"}],"outputs":[]},{"stateMutability":"nonpayable","type":"function","name":"replaceOwner","inputs":[{"name":"_new_owner","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"replaceGovernanceContract","inputs":[{"name":"_new_governance","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"replaceFundsAllocator","inputs":[{"name":"_new_funds_allocator","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"view","type":"function","name":"adapter_list","inputs":[],"outputs":[{"name":"","type":"address[]"}]},{"stateMutability":"nonpayable","type":"function","name":"set_strategy","inputs":[{"name":"_proposer","type":"address"},{"name":"_strategies","type":"tuple[5]","components":[{"name":"adapter","type":"address"},{"name":"ratio","type":"uint256"}]},{"name":"_min_proposer_payout","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"set_strategy","inputs":[{"name":"_proposer","type":"address"},{"name":"_strategies","type":"tuple[5]","components":[{"name":"adapter","type":"address"},{"name":"ratio","type":"uint256"}]},{"name":"_min_proposer_payout","type":"uint256"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"add_adapter","inputs":[{"name":"_adapter","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_adapter","inputs":[{"name":"_adapter","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_adapter","inputs":[{"name":"_adapter","type":"address"},{"name":"_rebalance","type":"bool"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_adapter","inputs":[{"name":"_adapter","type":"address"},{"name":"_rebalance","type":"bool"},{"name":"_force","type":"bool"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_adapter","inputs":[{"name":"_adapter","type":"address"},{"name":"_rebalance","type":"bool"},{"name":"_force","type":"bool"},{"name":"_min_assets","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"remove_adapter","inputs":[{"name":"_adapter","type":"address"},{"name":"_rebalance","type":"bool"},{"name":"_force","type":"bool"},{"name":"_min_assets","type":"uint256"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"swap_adapters","inputs":[{"name":"_adapterOld","type":"address"},{"name":"_adapterNew","type":"address"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"swap_adapters","inputs":[{"name":"_adapterOld","type":"address"},{"name":"_adapterNew","type":"address"},{"name":"_force","type":"bool"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"swap_adapters","inputs":[{"name":"_adapterOld","type":"address"},{"name":"_adapterNew","type":"address"},{"name":"_force","type":"bool"},{"name":"_min_assets","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"totalAssetsCached","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalAssets","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalReturns","inputs":[],"outputs":[{"name":"","type":"int256"}]},{"stateMutability":"view","type":"function","name":"claimable_yield_fees_available","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"claimable_yield_fees_available","inputs":[{"name":"_current_assets","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"claimable_strategy_fees_available","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"claimable_strategy_fees_available","inputs":[{"name":"_current_assets","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"claimable_all_fees_available","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"claimable_all_fees_available","inputs":[{"name":"_current_assets","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_yield_fees","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_yield_fees","inputs":[{"name":"_asset_request","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_yield_fees","inputs":[{"name":"_asset_request","type":"uint256"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_strategy_fees","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_strategy_fees","inputs":[{"name":"_asset_request","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_strategy_fees","inputs":[{"name":"_asset_request","type":"uint256"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_all_fees","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_all_fees","inputs":[{"name":"_asset_request","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"claim_all_fees","inputs":[{"name":"_asset_request","type":"uint256"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"convertToShares","inputs":[{"name":"_asset_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"convertToAssets","inputs":[{"name":"_share_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"maxDeposit","inputs":[{"name":"_spender","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"previewDeposit","inputs":[{"name":"_asset_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"maxMint","inputs":[{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"previewMint","inputs":[{"name":"_share_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"mint","inputs":[{"name":"_share_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"mint","inputs":[{"name":"_share_amount","type":"uint256"},{"name":"_receiver","type":"address"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"maxWithdraw","inputs":[{"name":"_owner","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"previewWithdraw","inputs":[{"name":"_asset_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"maxRedeem","inputs":[{"name":"_owner","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"previewRedeem","inputs":[{"name":"_share_amount","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"redeem","inputs":[{"name":"_share_amount","type":"uint256"},{"name":"_receiver","type":"address"},{"name":"_owner","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"redeem","inputs":[{"name":"_share_amount","type":"uint256"},{"name":"_receiver","type":"address"},{"name":"_owner","type":"address"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"getCurrentBalances","inputs":[],"outputs":[{"name":"","type":"uint256"},{"name":"","type":"tuple[5]","components":[{"name":"adapter","type":"address"},{"name":"current","type":"uint256"},{"name":"last_value","type":"uint256"},{"name":"max_deposit","type":"int256"},{"name":"max_withdraw","type":"int256"},{"name":"ratio","type":"uint256"},{"name":"target","type":"uint256"},{"name":"delta","type":"int256"}]},{"name":"","type":"uint256"},{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"balanceAdapters","inputs":[{"name":"_target_asset_balance","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"balanceAdapters","inputs":[{"name":"_target_asset_balance","type":"uint256"},{"name":"_min_tasset_balance","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"balanceAdapters","inputs":[{"name":"_target_asset_balance","type":"uint256"},{"name":"_min_tasset_balance","type":"uint256"},{"name":"_withdraw_only","type":"bool"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"balanceAdapters","inputs":[{"name":"_target_asset_balance","type":"uint256"},{"name":"_min_tasset_balance","type":"uint256"},{"name":"_withdraw_only","type":"bool"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"deposit","inputs":[{"name":"_asset_amount","type":"uint256"},{"name":"_receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"deposit","inputs":[{"name":"_asset_amount","type":"uint256"},{"name":"_receiver","type":"address"},{"name":"_min_shares","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"deposit","inputs":[{"name":"_asset_amount","type":"uint256"},{"name":"_receiver","type":"address"},{"name":"_min_shares","type":"uint256"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[{"name":"_asset_amount","type":"uint256"},{"name":"_receiver","type":"address"},{"name":"_owner","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[{"name":"_asset_amount","type":"uint256"},{"name":"_receiver","type":"address"},{"name":"_owner","type":"address"},{"name":"_min_assets","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"withdraw","inputs":[{"name":"_asset_amount","type":"uint256"},{"name":"_receiver","type":"address"},{"name":"_owner","type":"address"},{"name":"_min_assets","type":"uint256"},{"name":"pregen_info","type":"bytes[]"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"nonpayable","type":"function","name":"transfer","inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"transferFrom","inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"approve","inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},{"stateMutability":"nonpayable","type":"function","name":"claimRewards","inputs":[{"name":"_adapter","type":"address"},{"name":"reciepent","type":"address"}],"outputs":[]},{"stateMutability":"view","type":"function","name":"name","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"symbol","inputs":[],"outputs":[{"name":"","type":"string"}]},{"stateMutability":"view","type":"function","name":"decimals","inputs":[],"outputs":[{"name":"","type":"uint8"}]},{"stateMutability":"view","type":"function","name":"asset","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"governance","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"funds_allocator","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"adapters","inputs":[{"name":"arg0","type":"uint256"}],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"current_proposer","inputs":[],"outputs":[{"name":"","type":"address"}]},{"stateMutability":"view","type":"function","name":"min_proposer_payout","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"strategy","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"tuple","components":[{"name":"ratio","type":"uint256"},{"name":"last_asset_value","type":"uint256"}]}]},{"stateMutability":"view","type":"function","name":"total_assets_deposited","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"total_assets_withdrawn","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"total_yield_fees_claimed","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"total_strategy_fees_claimed","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"totalSupply","inputs":[],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"balanceOf","inputs":[{"name":"arg0","type":"address"}],"outputs":[{"name":"","type":"uint256"}]},{"stateMutability":"view","type":"function","name":"allowance","inputs":[{"name":"arg0","type":"address"},{"name":"arg1","type":"address"}],"outputs":[{"name":"","type":"uint256"}]}]
Contract Creation Code
615d66515034610255576020615f0a5f395f516040602082615f0a015f395f5111610255576020602082615f0a015f395f51018082615f0a0160403950506020615f2a5f395f516020602082615f0a015f395f5111610255576020602082615f0a015f395f51018082615f0a0160a03950506020615f4a5f395f518060081c6102555760e0526020615f6a5f395f518060a01c61025557610100526020615f8a5f395f518060a01c61025557610120526020615faa5f395f518060a01c61025557610140526020615fca5f395f518060140b8118610255576101605261016051615c86526020604051015f81601f0160051c6003811161025557801561012057905b8060051b604001518160051b602001615c860152600101818118610101575b505050602060a051015f81601f0160051c6002811161025557801561016057905b8060051b60a001518160051b608001615c860152600101818118610141575b50505060e051615d465261010051615d6652335f5561012051600155610140516002555f6014556101005160a05160c0206040516060207fb0d2618aac9d604947deb202f5160d0d0634c297f796d7c568441172490c41f660e051610180526020610180a45f337fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c5f610180a35f610120517f3aaaebeb4821d6a7e5c77ece53cff0afcc56c82add2c978dbbb7f73e84cbcfd25f610180a35f610140517f55b78759f76af43b8df65e695ca7be30a78c78d2717322edb8141fb5a02389bf5f610180a3615c8661025961000039615d86610000f35b5f80fd5f3560e01c60056005600a8306026159d401601b395f5160088160ff16838360181c0260181c0660031b8260081c61ffff1601601839505f51818160201c14600336111661004c57611ab8565b8061fffe163610348260011602176159d0578060101c61ffff16565b6020806040528060400160206020615ca65f395f510180615ca68339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b6020806040528060400160206020615d065f395f510180615d068339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b6020615d4660403960206040f35b6020615d6660403960206040f35b5f5460405260206040f35b60015460405260206040f35b60025460405260206040f35b6004356003548110156159d0576004015460405260206040f35b600d5460405260206040f35b600e5460405260206040f35b6004358060a01c6159d057604052600f6040516020525f5260405f20805460605260018101546080525060406060f35b60105460405260206040f35b60115460405260206040f35b60125460405260206040f35b60135460405260206040f35b60145460405260206040f35b6004358060a01c6159d05760405260156040516020525f5260405f205460605260206060f35b6004358060a01c6159d0576040526024358060a01c6159d05760605260166040516020525f5260405f20806060516020525f5260405f2090505460805260206080f35b6004358060a01c6159d0576040525f543318156102d157602a6060527f4f6e6c79206578697374696e67206f776e65722063616e207265706c616365206080527f746865206f776e65722e0000000000000000000000000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b60405161033457601d6060527f4f776e65722063616e6e6f74206265206e756c6c20616464726573732e00000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b5f546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c5f6060a36040515f55600160605260206060f35b6004358060a01c6159d0576040526001543318156104065760356060527f4f6e6c79206578697374696e6720476f7665726e616e636520636f6e747261636080527f74206d6179207265706c61636520697473656c662e000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b60405161048d5760226060527f476f7665726e616e63652063616e6e6f74206265206e756c6c206164647265736080527f732e00000000000000000000000000000000000000000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6001546040517f3aaaebeb4821d6a7e5c77ece53cff0afcc56c82add2c978dbbb7f73e84cbcfd25f6060a3604051600155600160605260206060f35b6004358060a01c6159d0576040525f543318156105605760346060527f4f6e6c79206f776e65722063616e206368616e6765207468652066756e6473206080527f616c6c6f636174696f6e20636f6e74726163742100000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516105e75760266060527f46756e6473416c6c6f6361746f722063616e6e6f74206265206e756c6c2061646080527f64726573732e000000000000000000000000000000000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6002546040517f55b78759f76af43b8df65e695ca7be30a78c78d2717322edb8141fb5a02389bf5f6060a3604051600255600160605260206060f35b602080604052806040015f6003548083528060051b5f82600581116159d057801561066457905b80600401548160051b60208801015260010181811861064a575b505082016020019150509050810190506040f35b5f6201c960526106ec565b6101843560040160058135116159d05780355f81600581116159d05780156106e157905b8060051b60208501013560208501016110008135116159d057602081350161102083026201c98001818382375050506001018181186106a7575b5050806201c9605250505b6004358060a01c6159d0576201c800526024358060a01c6159d0576201c820526044356201c840526064358060a01c6159d0576201c860526084356201c8805260a4358060a01c6159d0576201c8a05260c4356201c8c05260e4358060a01c6159d0576201c8e052610104356201c90052610124358060a01c6159d0576201c92052610144356201c940526201c8005162017460526101406201c820620174805e61016435620175c0526201c960515f81600581116159d05780156107d857905b61102081026201c980016020815101611020830262017600018183825e5050506001018181186107ad575b505080620175e052506107ed62021a40613574565b62021a405162021a2052600160405260016060525f60805261080d612765565b602062021a20f35b6004358060a01c6159d057610560526020610560516104e052610839610580613bba565b610580f35b60016201750052606036620175203761095f565b6024358060011c6159d0576201750052606036620175203761095f565b6024358060011c6159d05762017500526044358060011c6159d0576201752052604036620175403761095f565b6024358060011c6159d05762017500526044358060011c6159d057620175205260643562017540525f620175605261095f565b6024358060011c6159d05762017500526044358060011c6159d0576201752052606435620175405260843560040160058135116159d05780355f81600581116159d057801561095457905b8060051b60208501013560208501016110008135116159d0576020813501611020830262017580018183823750505060010181811861091a575b505080620175605250505b6004358060a01c6159d057620174e0526020620174e051620122205262017560515f81600581116159d05780156109bd57905b611020810262017580016020815101611020830262012260018183825e505050600101818118610992575b505080620122405250606062017500620173005e6109dd6201c620613d5e565b6201c620f35b60403661068037610a1f565b6044358060011c6159d057610680525f6106a052610a1f565b6044358060011c6159d057610680526064356106a0525b6004358060a01c6159d057610640526024358060a01c6159d05761066052602060806106406104e05e610a536106c061443d565b6106c0f35b6020610a65610120611fe3565b610120f35b6020610a7660c0611abc565b60c0f35b610a85610140611abc565b610140516101205260206101205160c052610aa1610140611b6c565b610140f35b5f61020052610ab8565b600435610200525b604036610220376102005161012052610ad2610260611bf4565b610260805161022052602081015161024052506020610220f35b5f61020052610afe565b600435610200525b604036610220376102005161012052610b18610260611bf4565b610260805161022052602081015161024052506020610240f35b5f61020052610b44565b600435610200525b604036610220376102005161012052610b5e610260611bf4565b6102608051610220526020810151610240525061022051610240518082018281106159d05790509050610260526020610260f35b6040366201746037610c22565b60043562017460525f6201748052610c22565b600435620174605260243560040160058135116159d05780355f81600581116159d0578015610c1757905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174a00181838237505050600101818118610bdd575b505080620174805250505b6020600262012220526201746051620122405262017480515f81600581116159d0578015610c7757905b6110208102620174a0016020815101611020830262012280018183825e505050600101818118610c4c575b5050806201226052506040366201732037610c946201c540613133565b6201c540f35b6040366201746037610d2a565b60043562017460525f6201748052610d2a565b600435620174605260243560040160058135116159d05780355f81600581116159d0578015610d1f57905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174a00181838237505050600101818118610ce5575b505080620174805250505b6020600462012220526201746051620122405262017480515f81600581116159d0578015610d7f57905b6110208102620174a0016020815101611020830262012280018183825e505050600101818118610d54575b5050806201226052506040366201732037610d9c6201c540613133565b6201c540f35b6040366201746037610e32565b60043562017460525f6201748052610e32565b600435620174605260243560040160058135116159d05780355f81600581116159d0578015610e2757905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174a00181838237505050600101818118610ded575b505080620174805250505b6020600162012220526201746051620122405262017480515f81600581116159d0578015610e8757905b6110208102620174a0016020815101611020830262012280018183825e505050600101818118610e5c575b5050806201226052506040366201732037610ea46201c540613133565b6201c540f35b602060043561034052610ebe610300611abc565b610300516103605260406103406102005e610eda610320614878565b610320f35b602060043561034052610ef3610300611abc565b610300516103605260406103406102005e610f0f6103206149ae565b610320f35b6004358060a01c6159d0576040526f7fffffffffffffffffffffffffffffff60605260206060f35b602060043561034052610f50610300611abc565b610300516103605260406103406102005e610f6c610320614878565b610320f35b6004358060a01c6159d0576040526f7fffffffffffffffffffffffffffffff60605260206060f35b602060043561034052610fad610300611abc565b610300516103605260406103406102005e610fc96103206149ae565b610320f35b5f620174a052611041565b60443560040160058135116159d05780355f81600581116159d057801561103657905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174c00181838237505050600101818118610ffc575b505080620174a05250505b6024358060a01c6159d05762017480526004356201c5c0526110656201c580611fe3565b6201c580516201c5e05260406201c5c06102005e6110856201c5a06149ae565b6201c5a0516201c560526040366201c580376201c560516201222052620174805162012240525f6201226052620174a0515f81600581116159d05780156110f357905b6110208102620174c00160208151016110208302620122a0018183825e5050506001018181186110c8575b5050806201228052506111086201c5c0614bc4565b6201c5c080516201c5805260208101516201c5a05250600160405260016060525f608052611134612765565b60206201c5a0f35b6004358060a01c6159d0576103005260206015610300516020525f5260405f20546103605261116c610320611abc565b610320516103805260406103606102005e6111886103406149ae565b610340f35b6020600435610340526111a1610300611abc565b610300516103605260406103406102005e6111bd610320614878565b610320f35b6004358060a01c6159d05760405260156040516020525f5260405f205460605260206060f35b6020600435610340526111fc610300611abc565b610300516103605260406103406102005e6112186103206149ae565b610320f35b5f6201746052611290565b60643560040160058135116159d05780355f81600581116159d057801561128557905b8060051b60208501013560208501016110008135116159d0576020813501611020830262017480018183823750505060010181811861124b575b505080620174605250505b6024358060a01c6159d05762017420526044358060a01c6159d05762017440526004356201c580526112c46201c540611fe3565b6201c540516201c5a05260406201c5806102005e6112e46201c5606149ae565b6201c560516201c520526040366201c540376201c52051620122205262017420516201224052620174405162012260525f620122805262017460515f81600581116159d057801561135c57905b6110208102620174800160208151016110208302620122c0018183825e505050600101818118611331575b505080620122a052506113716201c580615229565b6201c58080516201c5405260208101516201c5605250600160405260016060525f60805261139d612765565b60206201c560f35b610560366106a0376113b8610c00612367565b610c0080516106a05260208101610500816106c05e50610520810151610bc052610540810151610be05250600160405260016060525f6080526113f9612765565b6106a051610c00526105006106c0610c205e6040610bc06111205e610560610c00f35b60603662012220376114e1565b602435620122205260403662012240376114e1565b60243562012220526044358060011c6159d05762012240525f62012260526114e1565b60243562012220526044358060011c6159d057620122405260643560040160058135116159d05780355f81600581116159d05780156114d657905b8060051b60208501013560208501016110008135116159d0576020813501611020830262012280018183823750505060010181811861149c575b505080620122605250505b5f5433181561157e57602362017320527f6f6e6c79206f776e65722063616e2063616c6c2062616c616e6365416461707462017340527f6572730000000000000000000000000000000000000000000000000000000000620173605262017320506201732051806201734001601f825f031636823750506308c379a0620172e05260206201730052601f19601f62017320510116604401620172fcfd5b60043561c44052620122205161c4605262012260515f81600581116159d05780156115cf57905b611020810262012280016020815101611020830261c4a0018183825e5050506001018181186115a5575b50508061c4805250620122405162011540526115ed62017340612cc5565b62017340516201732052600160405260016060525f60805261160d612765565b602062017320f35b604036620174a0376116a5565b604435620174a0525f620174c0526116a5565b604435620174a05260643560040160058135116159d05780355f81600581116159d057801561169a57905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174e00181838237505050600101818118611660575b505080620174c05250505b6024358060a01c6159d05762017480526040366201c580376004356201222052604062017480620122405e620174c0515f81600581116159d057801561171257905b6110208102620174e00160208151016110208302620122a0018183825e5050506001018181186116e7575b5050806201228052506117276201c5c0614bc4565b6201c5c080516201c5805260208101516201c5a05250600160405260016060525f608052611753612765565b60206201c580f35b60403662017460376117eb565b60643562017460525f62017480526117eb565b606435620174605260843560040160058135116159d05780355f81600581116159d05780156117e057905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174a001818382375050506001018181186117a6575b505080620174805250505b6024358060a01c6159d05762017420526044358060a01c6159d05762017440526040366201c540376004356201222052606062017420620122405e62017480515f81600581116159d057801561186857905b6110208102620174a00160208151016110208302620122c0018183825e50505060010181811861183d575b505080620122a0525061187d6201c580615229565b6201c58080516201c5405260208101516201c5605250600160405260016060525f6080526118a9612765565b60206201c540f35b6004358060a01c6159d0576101005233604052610100516060526024356080526118d9615677565b6001610120526020610120f35b6004358060a01c6159d057610120526024358060a01c6159d0576101405233604052604061012060605e60443560a05261191e6157e0565b6001610160526020610160f35b6004358060a01c6159d05760c0523360405260c05160605260243560805261195161578b565b600160e052602060e0f35b6004358060a01c6159d0576040526024358060a01c6159d0576060525f543318156119dd57601c6080527f4f6e6c79206f776e65722063616e20636c61696d52657761726473210000000060a0526080506080518060a001601f825f031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6040515f6080525f600354600581116159d0578015611a1857905b80600401548318611a0d576001608052611a18565b6001018181186119f8575b50506080519050611a7f57601360a0527f4e6f7420612076616c696420616461707465720000000000000000000000000060c05260a05060a0518060c001601f825f031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b6040515a63ef5cfb8c608452600460605160a4526020016080526080505f5f60805160a08585f490509050611ab6573d5f5f3e3d5ffd5b005b5f5ffd5b6020615d665f395f516370a0823160605230608052602060606024607c845afa611ae8573d5f5f3e3d5ffd5b60203d106159d05760609050516040525f600354600581116159d0578015611b6257905b80600401546060526040516060516301e1d114608052602060806004609c845afa611b39573d5f5f3e3d5ffd5b60203d106159d05760809050518082018281106159d05790509050604052600101818118611b0c575b5050604051815250565b60c05160e05260e051611b8c57611b84610100611abc565b6101005160e0525b60115460e0518082018281106159d057905090506012548082018281106159d057905090506013548082018281106159d057905090508060ff1c6159d0576010548060ff1c6159d0578082038281135f8312186159d057905090506101005261010051815250565b610120516101405261014051611c1857611c0f610160611abc565b61016051610140525b6101405160c052611c2a610180611b6c565b61018051610160525f6101605113611c4b575f81525f602082015250611cf8565b60403661018037610160515f81126159d0578060011b818160011c186159d05790506064810490506101c052610160515f81126159d0576001811517156159d0575f90506064810490506101e0526101c0516012541015611cc0576101c0516012548082038281116159d05790509050610180525b6101e0516013541015611ce7576101e0516013548082038281116159d057905090506101a0525b6101805181526101a0516020820152505b565b604036610260376102405161012052611d146102a0611bf4565b6102a08051610260526020810151610280525060026102005118611d38575f610280525b60046102005118611d49575f610260525b600d54611d56575f610260525b60026102005118611d68576001611d71565b60016102005118155b611d7b575f611d81565b5f543314155b15611d8c575f610260525b60046102005118611d9e576001611da7565b60016102005118155b15611e5157600d543318611dbc576001611dc3565b6001543318155b611e5157603b6102a0527f4f6e6c7920637572656e742070726f706f736572206f7220676f7665726e616e6102c0527f6365206d617920636c61696d20737472617465677920666565732e00000000006102e0526102a0506102a051806102c001601f825f031636823750506308c379a061026052602061028052601f19601f6102a051011660440161027cfd5b61026051610280518082018281106159d05790509050610220511115611efb57602c6102a0527f4e6f7420656e6f756768206665657320746f2066756c66696c6c2072657175656102c0527f7374656420616d6f756e742e00000000000000000000000000000000000000006102e0526102a0506102a051806102c001601f825f031636823750506308c379a061026052602061028052601f19601f6102a051011660440161027cfd5b61026051815261028051602082015250565b600a5c611f55576020615d665f395f516370a0823160405230606052602060406024605c845afa611f40573d5f5f3e3d5ffd5b60203d106159d0576040905051600a5d5f600c5d5b600a5c815250565b604051611f6d575f815250611fe1565b600b6040516020525f5260405f205c60605260605115611f9257606051815250611fe1565b6040516301e1d114608052602060806004609c845afa611fb4573d5f5f3e3d5ffd5b60203d106159d0576080905051606052606051600b6040516020525f5260405f205d5f600c5d6060518152505b565b600c5c15611ff657600c5c815250612065565b61200060e0611f0d565b60e05160c0525f600354600581116159d057801561205657905b806004015460e05260c05160e051604052612036610100611f5d565b610100518082018281106159d0579050905060c05260010181811861201a575b505060c051600c5d60c0518152505b565b606051608052606051612111576040516402540be4007036f9bfb3af7b756fad5cd10396a21346cb82116159d057810290506020615c865f395f5164e8d4a510006402540be4008202058060140b81186159d05790508082028115838383051417156159d0576402540be40081058060140b81186159d0579050905090506402540be4005f82126159d0578105905060a05260405160a0518082038281116159d057905090506080525b608051604051101561219d57603260a0527f44657369726564206173736574732063616e6e6f74206265206c65737320746860c0527f616e206d696e696d756d2061737365747321000000000000000000000000000060e05260a05060a0518060c001601f825f031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b608051815250565b610120516121d6576121b8610160611fe3565b61016051610140518082038281116159d05790509050815250612228565b604061012060405e6121e9610160612067565b61016051610140526121fc610160611fe3565b6101605161012051610140518082038281116159d057905090508082038281116159d057905090508152505b565b60405163ac7a1b5b608052602060806004609c845afa61224c573d5f5f3e3d5ffd5b60203d106159d05760809050516060527f8000000000000000000000000000000000000000000000000000000000000000606051106122aa577f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060525b6060518060ff1c6159d057805f03600160ff1b82141582825f031416156159d0579050815250565b604051636083e59a608052602060806004609c845afa6122f4573d5f5f3e3d5ffd5b60203d106159d05760809050516060527f800000000000000000000000000000000000000000000000000000000000000060605110612356577f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff815250612365565b6060518060ff1c6159d0578152505b565b61237160e0611f0d565b60e05160c0526105003660e0376003546123ac5760c05181526020810161050060e0825e5060c0516105208201525f61054082015250612566565b60c0516105e052604036610600375f600354600581116159d057801561253d57905b8060040154610640526106405161062051600481116159d05760081b60e0015261064051604052612400610660611f5d565b6106605161062051600481116159d05760081b60e001602081019050526105e05161062051600481116159d05760081b60e001602081019050518082018281106159d057905090506105e0526106405160405261245e61066061222a565b6106605161062051600481116159d05760081b60e001608081019050526106405160405261248d6106606122d2565b6106605161062051600481116159d05760081b60e00160608101905052600f610640516020525f5260405f20805461066052600181015461068052506106605161062051600481116159d05760081b60e00160a0810190505261060051610660518082018281106159d05790509050610600526106805161062051600481116159d05760081b60e0016040810190505261062051600181018181106159d0579050610620526001018181186123ce575b505060c05181526020810161050060e0825e506105e05161052082015261060051610540820152505b565b6020615d665f395f516370a082316106005230610620526020610600602461061c845afa612598573d5f5f3e3d5ffd5b60203d106159d0576106009050516105e052600254633c64f7d8610600526105e0516106205260405161064052606060606106605e61050060c06106c05e6105c051610bc0526101e06106006105c461061c845afa6125f9573d5f5f3e3d5ffd5b6101e03d106159d05761060051610be052610620518060a01c6159d057610c005261064051610c2052610660518060a01c6159d057610c405261068051610c60526106a0518060a01c6159d057610c80526106c051610ca0526106e0518060a01c6159d057610cc05261070051610ce052610720518060a01c6159d057610d0052610740518060a01c6159d057610d2052610760518060a01c6159d057610d4052610780518060a01c6159d057610d60526107a0518060a01c6159d057610d80526107c0518060a01c6159d057610da052610be090506101e081835e5050565b6003546040511861275e575f615120525f600354600581116159d057801561275b57905b80600401546151405261514051615100511861273b57611020615120516040518110156159d0570260600160208151018082865e5050505050612763565b61512051600181018181106159d0579050615120526001018181186126fd575b50505b5f8152505b565b5f600c5d60405115612776575f600a5d5b606051156127d4576080516127c3575f600354600581116159d05780156127bc57905b806004015460a0525f600b60a0516020525f5260405f205d600101818118612799575b50506127d4565b5f600b6080516020525f5260405f205d5b565b6151a0515f81600581116159d057801561281457905b61102081026151c001602081510161102083026060018183825e5050506001018181186127ec575b50508060405250615160516151005261282e61b2806126d9565b61b2806020815101808261a2605e50505f61b280526151605160405261285561b2e0611f5d565b61b2e05161b2c052615160515a635d30351961b2e452600460406151805161b304528061b324528061b30401602061a26051018061a260835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190500161b2e05261b2e050602061c3a061b2e05161b3008585f4905090506128dc573d5f5f3e3d5ffd5b3d602081183d602010021861c3805261c3806020815101808261b2805e50506001604052600160605261516051608052612914612765565b6151605160405261292661b300611f5d565b61b3005161b2e05261b2e051600f615160516020525f5260405f2060018101905055565b6151c0515f81600581116159d057801561298857905b61102081026151e001602081510161102083026060018183825e505050600101818118612960575b5050806040525061516051615100526129a261b2c06126d9565b61b2c06020815101808261a2a05e50506020615d665f395f516370a0823161b2e0526151a05161b30052602061b2e0602461b2fc845afa6129e5573d5f5f3e3d5ffd5b60203d106159d05761b2e090505161b2c0525f61b2e052600161b3205261516051612a6f57600e61b340527f454d50545920414441505445522100000000000000000000000000000000000061b3605261b3405061b340518061b36001601f825f031636823750506308c379a061b30052602061b32052601f19601f61b34051011660440161b31cfd5b6151a051612adc57601261b340527f454d5054592057495448445241575f544f21000000000000000000000000000061b3605261b3405061b340518061b36001601f825f031636823750506308c379a061b30052602061b32052601f19601f61b34051011660440161b31cfd5b61a28051612b8857615160515a6362b2b5f061b3445260046060604061518061b3645e8061b3a4528061b36401602061a2a051018061a2a0835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190500161b3405261b34050602061c42061b3405161b3608585f490509050612b64573d5f5f3e3d5ffd5b3d602081183d602010021861c4005261c4006020815101808261b2e05e5050612c20565b615160515a6362b2b5f061b3445260046060604061518061b3645e8061b3a4528061b36401602061a2a051018061a2a0835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190500161b3405261b34050602061c42061b3405161b3608585f49050905061b320523d602081183d602010021861c4005261c4006020815101808261b2e05e50505b6001604052600160605261516051608052612c39612765565b6020615d665f395f516370a0823161b360526151a05161b38052602061b360602461b37c845afa612c6c573d5f5f3e3d5ffd5b60203d106159d05761b36090505161b3405261516051604052612c9061b360611f5d565b61b36051600f615160516020525f5260405f206001810190505561b3405161b2c0518082038281116159d05790509050815250565b6101e0366201156037604061c4406101205e612ce3620117606121a5565b62011760516201174052600354612d3f576020615d665f395f516370a08231620117605230620117805260206201176060246201177c845afa612d28573d5f5f3e3d5ffd5b60203d106159d05762011760905051815250613131565b610560366201176037612d5462011cc0612367565b62011cc0805162011760526020810161050081620117805e5061052081015162011c805261054081015162011ca0525061c44051604052600e54606052604062011c8060805e6105006201178060c05e62011540516105c052612db962011cc0612568565b62011cc061014081620115605e610140810160a081620116a05e50505f6005905b8060051b620116a0015162011cc05262011cc051612df757612ed2565b600f62011cc0516020525f5260405f20805462011ce052600181015462011d0052505f62011ce052600f62011cc0516020525f5260405f2062011ce051815562011d005160018201555062011cc051604052612e5562011d40611f5d565b62011d405162011d2052620117405162011d005162011d20518082038281116159d057905090508082038281116159d05790509050620117405262011cc0517f8af0bf5fccd11158fcb7ce9747ad88f3bc6f4c3d21019bc157b1fea3f052ddcc604062011d0062011d405e604062011d40a2600101818118612dda575b50505f6005905b8060061b620115600160408162011cc05e5062011ce051612ef95761307a565b62011cc051612f075761306f565b600e548060ff1c6159d05762011cc0511215612fe7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff62011cc0511361306f5762011cc051805f03600160ff1b82141582825f031416156159d05790505f81126159d05762011d0052604062011ce06151605e306151a05261c480515f81600581116159d0578015612fbf57905b611020810261c4a001602081510161102083026151e0018183825e505050600101818118612f96575b5050806151c052505f61a28052612fd862011d4061294a565b62011d405162011d205261306f565b62011cc0515f81126159d057612fff62011d20611f0d565b62011d20518082811882841002189050905062011d0052604062011ce06151605e61c480515f81600581116159d057801561305f57905b611020810261c4a001602081510161102083026151c0018183825e505050600101818118613036575b5050806151a0525061306f6127d6565b600101818118612ed9575b505061308862011ce0611fe3565b62011ce05162011cc05262011740516130a362011ce0611fe3565b62011ce051101561311c57601262011d00527f536c69707061676520657863656564656421000000000000000000000000000062011d205262011d005062011d00518062011d2001601f825f031636823750506308c379a062011cc052602062011ce052601f19601f62011d0051011660440162011cdcfd5b61312862011ce0611f0d565b62011ce0518152505b565b60403662017360376040620122206102005e62017320516102405261315a620173a0611cfa565b620173a0805162017360526020810151620173805250620173605162017380518082018281106159d05790509050620173a0526201224051156131a2576201224051620173a0525b6131ae620173e0611f0d565b620173e051620173c052620173a051620173c051106131e857620173a051620173c05180828118828410021890509050620173a052613273565b620173a05161c44052620173405161c4605262012260515f81600581116159d057801561323b57905b611020810262012280016020815101611020830261c4a0018183825e505050600101818118613211575b50508061c480525060016201154052613256620173e0612cc5565b620173e051620173a05180828118828410021890509050620173a0525b620173805115613289576201736051151561328b565b5f5b6132b7576201738051156132a857620173a05162017380526133b9565b620173a05162017360526133b9565b62017380516402540be4007036f9bfb3af7b756fad5cd10396a21346cb82116159d05781029050620173805162017360518082018281106159d057905090506402540be4007036f9bfb3af7b756fad5cd10396a21346cb82116159d0578102905080156159d057806402540be4008302058060140b81186159d05790509050620173a0516402540be4007036f9bfb3af7b756fad5cd10396a21346cb82116159d057810290508082028115838383051417156159d0576402540be40081058060140b81186159d0579050905090506402540be4005f82126159d057810590506201738052620173a05162017380518082038281116159d0579050905062017360525b60125462017360518082018281106159d0579050905060125560135462017380518082018281106159d0579050905060135562017380511561340157600d545f541415613403565b5f5b156134aa57600d543318613418576001613423565b600e54620173805110155b156134a3576020615d665f395f5163a9059cbb620173e052600d546201740052620173805162017420526020620173e06044620173fc5f855af1613469573d5f5f3e3d5ffd5b3d61348157803b156159d0576001620174405261349c565b60203d106159d057620173e0518060011c6159d05762017440525b6201744050505b5f62017380525b620173605162017380518082018281106159d0579050905015613554576020615d665f395f5163a9059cbb620173e0525f546201740052620173605162017380518082018281106159d0579050905062017420526020620173e06044620173fc5f855af161351a573d5f5f3e3d5ffd5b3d61353257803b156159d0576001620174405261354d565b60203d106159d057620173e0518060011c6159d05762017440525b6201744050505b600160405260016060525f60805261356a612765565b620173a051815250565b60015433181561361257602b6201c6a0527f4f6e6c7920476f7665726e616e63652044414f206d6179207365742061206e656201c6c0527f772073747261746567792e0000000000000000000000000000000000000000006201c6e0526201c6a0506201c6a051806201c6c001601f825f031636823750506308c379a06201c6605260206201c68052601f19601f6201c6a05101166044016201c67cfd5b620174605161368957601f6201c6a0527f50726f706f7365722063616e2774206265206e756c6c20616464726573732e006201c6c0526201c6a0506201c6a051806201c6c001601f825f031636823750506308c379a06201c6605260206201c68052601f19601f6201c6a05101166044016201c67cfd5b6201746051600d5414613778576136a26201c6c0611abc565b6201c6c0516201c6a0526040366201c6c0376201c6a051610120526136c96201c700611bf4565b6201c70080516201c6c05260208101516201c6e05250600e546201c6e051111561376757600462012220525f6201224052620175e0515f81600581116159d057801561373c57905b611020810262017600016020815101611020830262012280018183825e505050600101818118613711575b5050806201226052506201c6a05162017320525f62017340526137616201c700613133565b6201c700505b6201746051600d55620175c051600e555b5f600354600581116159d05780156137b357905b80600401546201c6a0525f600f6201c6a0516020525f5260405f205560010181811861378c575b50505f6005905b8060061b62017480016040816201c6a05e506040366201c6e0376201c6c0516201c6e052600f6201c6a0516020525f5260405f20600181019050546201c70052600f6201c6a0516020525f5260405f206201c6e05181556201c700516001820155506001018181186137ba5750507f357e53e5fd1ca670f6f6f6174e30cb36eda3d81b8ca610e6cc90668610c810f4610140620174806201c6a05e62017460516201c7e0526101606201c6a0a16001815250565b604051156139d55760405163ed2127186101e0526101806101e060046101fc845afa61389c573d5f5f3e3d5ffd5b60403d106159d0576101e0516101e001600a8151116159d05780515f81600a81116159d05780156138ef57905b8060051b6020850101518060a01c6159d0578160051b6103a001526001018181186138c9575b5050806103805250506103809050805160208160051b01808360805e5050505f608051600a81116159d05780156139d257905b8060051b60a001516101e05260096101e0516020525f5260405f2054610200526060516102005118156139b457601e610220527f696e636f6d696e6720746f6b656e20616c72656164792068616e646c656400006102405261022050610220518061024001601f825f031636823750506308c379a06101e052602061020052601f19601f6102205101166044016101fcfd5b60405160096101e0516020525f5260405f2055600101818118613922575b50505b60605115613bb85760605163ed2127186101e0526101806101e060046101fc845afa613a03573d5f5f3e3d5ffd5b60403d106159d0576101e0516101e001600a8151116159d05780515f81600a81116159d0578015613a5657905b8060051b6020850101518060a01c6159d0578160051b6103a00152600101818118613a30575b5050806103805250506103809050805160208160051b01808360805e5050505f608051600a81116159d0578015613bb557905b8060051b60a001516101e05260096101e0516020525f5260405f205461020052604051613b3857606051610200511815613b2257601e610220527f6f7574676f696e6720746f6b656e20616c72656164792068616e646c656400006102405261022050610220518061024001601f825f031636823750506308c379a06101e052602061020052601f19601f6102205101166044016101fcfd5b5f60096101e0516020525f5260405f2055613baa565b604051610200511815613baa57601e610220527f6f7574676f696e6720746f6b656e20616c72656164792068616e646c656400006102405261022050610220518061024001601f825f031636823750506308c379a06101e052602061020052601f19601f6102205101166044016101fcfd5b600101818118613a89575b50505b565b5f54331815613c4d576028610500527f4f6e6c79206f776e65722063616e20616464206e6577204c656e64696e672041610520527f646170746572732e0000000000000000000000000000000000000000000000006105405261050050610500518061052001601f825f031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b6104e0515f610500525f600354600581116159d0578015613c8b57905b80600401548318613c8057600161050052613c8b565b600101818118613c6a575b505061050051905015613cfd57601a610520527f6164617074657220616c726561647920737570706f727465642e0000000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b600354600481116159d0576104e051816004015560018101600355506104e0516040525f606052613d2c61386e565b6104e051337f4b3749a16ab97cf0e9866299c183369da7570769bb78bd2c62a7df5c8da426315f610500a36001815250565b5f54331815613dfb57602762017360527f4f6e6c79206f776e65722063616e2072656d6f7665204c656e64696e6720416462017380527f6170746572732e00000000000000000000000000000000000000000000000000620173a05262017360506201736051806201738001601f825f031636823750506308c379a0620173205260206201734052601f19601f620173605101166044016201733cfd5b6201222051600162017360525f600354600581116159d0578015613e3c57905b80600401548318613e31575f6201736052613e3c565b600101818118613e1b575b50506201736051905015613e53575f81525061443b565b6201222051604052613e6762017380611f5d565b6201738051620173605262017360516040526201734051606052613e8d620173a0612067565b620173a0516201738052620173605162017380518082038281116159d05790509050620173a0525f600f62012220516020525f5260405f2055600162017300511861413a57613ede620173e0611fe3565b620173e051620173c0525f61c44052620173a05161c4605262012240515f81600581116159d0578015613f3757905b611020810262012260016020815101611020830261c4a0018183825e505050600101818118613f0d575b50508061c48052505f6201154052613f51620173e0612cc5565b620173e050620173205161432257613f6b62017400611fe3565b6201740051620173e052620173c051620173e051101561432257620173c051620173e0518082038281116159d05790509050620174005262017400516201736051101561406c57605062017420527f4552524f52202d206c6f7373207761732067726561746572207468616e20616462017440527f6170746572206173736574732e2054727920746f2072656d6f7665207769746862017460527f6f757420726562616c616e63696e672e00000000000000000000000000000000620174805262017420506201742051806201744001601f825f031636823750506308c379a0620173e05260206201740052601f19601f62017420510116604401620173fcfd5b6201740051620173a051101561432257604e62017420527f4552524f52202d20746f6f206d75636820736c6970706167652072656d6f766962017440527f6e6720616461707465722e2054727920746f2072656d6f766520776974686f7562017460527f7420726562616c616e63696e672e000000000000000000000000000000000000620174805262017420506201742051806201744001601f825f031636823750506308c379a0620173e05260206201740052601f19601f62017420510116604401620173fcfd614322565b62017360511561432257620122205161516052620173605161518052306151a05262012240515f81600581116159d057801561419c57905b61102081026201226001602081510161102083026151e0018183825e505050600101818118614172575b5050806151c05250620173205161a280526141b9620173e061294a565b620173e051620173c05262017320516143225762012220516040526141e0620173e0611f5d565b620173e0511561427e57603762017400527f4552524f52202d2061646170746572206164617074657220746f20626520726562017420527f6d6f766564207374696c6c206861732061737365747321000000000000000000620174405262017400506201740051806201742001601f825f031636823750506308c379a0620173c0526020620173e052601f19601f62017400510116604401620173dcfd5b620173c0516201738051111561432257602e620173e0527f4552524f52202d20746f6f206d75636820736c697070616765206f6e2061646162017400527f707465722077697468647261772e0000000000000000000000000000000000006201742052620173e050620173e051806201740001601f825f031636823750506308c379a0620173a0526020620173c052601f19601f620173e0510116604401620173bcfd5b5f620173c0525f600354600581116159d057801561438757905b80600401546201748052620122205162017480511461437c57620173c051600481116159d05762017480518160051b620173e0015260018101620173c052505b60010181811861433c575b5050620173c05160208160051b015f81601f0160051c600681116159d05780156143c757905b8060051b620173c0015181600301556001018181186143ad575b505050505f60405262012220516060526143df61386e565b6201222051337f25a12528a39d56c4ad0183f3bbb17f4d36cb1bcf8f360da144ad4fd321f78eae620122205160405261441a62017480611f5d565b6201748051620174a0526201732051620174c0526040620174a0a360018152505b565b5f543318156144d0576025610560527f4f6e6c79206f776e65722063616e2073776170204c656e64696e672041646170610580527f746572732e0000000000000000000000000000000000000000000000000000006105a05261056050610560518061058001601f825f031636823750506308c379a061052052602061054052601f19601f61056051011660440161053cfd5b6104e051156144e4576105005115156144e6565b5f5b614574576025610560527f43616e2774206861766520656d707479206164647265737320666f7220616461610580527f707465722e0000000000000000000000000000000000000000000000000000006105a05261056050610560518061058001601f825f031636823750506308c379a061052052602061054052601f19601f61056051011660440161053cfd5b6104e051604052614586610580611f5d565b6105805161056052610500516040526145a06105a0611f5d565b6105a05161058052610520516145bb576105605115156145bd565b5f5b1561468957610560516105805110156146895761056051604052610540516060526145e96105c0612067565b6105c0516105a052610580516105a05111156146895760266105c0527f4552524f52202d20537761702065786365656473206d6178696d756d20736c696105e0527f70706167652e0000000000000000000000000000000000000000000000000000610600526105c0506105c051806105e001601f825f031636823750506308c379a06105805260206105a052601f19601f6105c051011660440161059cfd5b6040366105a0375f600354600581116159d05780156146e557905b80600401546105e0526104e0516105e051186146c55760016105c0526146e5565b6105a051600181018181106159d05790506105a0526001018181186146a4575b50506105c0516147795760256105e0527f4164617074657220746f206265207265706c6163656420776173206e6f742066610600527f6f756e642e000000000000000000000000000000000000000000000000000000610620526105e0506105e0518061060001601f825f031636823750506308c379a06105a05260206105c052601f19601f6105e05101166044016105bcfd5b610500516105a0516003548110156159d05760040155600f6104e0516020525f5260405f2054600f610500516020525f5260405f205561058051600f610500516020525f5260405f2060018101905055600f6104e0516020525f5260405f205f81555f600182015550610500516040526104e0516060526147f861386e565b6104e051337f25a12528a39d56c4ad0183f3bbb17f4d36cb1bcf8f360da144ad4fd321f78eae6104e0516040526148306105e0611f5d565b6105e0516106005261052051610620526040610600a361050051337f4b3749a16ab97cf0e9866299c183369da7570769bb78bd2c62a7df5c8da426315f6105e0a36001815250565b601454610240526040366102603761022051610120526148996102a0611bf4565b6102a08051610260526020810151610280525061026051610280518082018281106159d057905090506102a052610240516148da57610200518152506149ac565b610220516148ee57610200518152506149ac565b6102a0516102205110156149615760206102c0527f5f636f6e76657274546f5368617265732073616e697479206661696c757265216102e0526102c0506102c051806102e001601f825f031636823750506308c379a06102805260206102a052601f19601f6102c051011660440161029cfd5b610220516102a0518082038281116159d057905090506102c05261020051610240518082028115838383041417156159d057905090506102c05180156159d057808204905090508152505b565b601454610240526040366102603761022051610120526149cf6102a0611bf4565b6102a08051610260526020810151610280525061026051610280518082018281106159d057905090506102a0526102a051610220511015614a6f5760206102c0527f5f636f6e76657274546f4173736574732073616e697479206661696c757265216102e0526102c0506102c051806102e001601f825f031636823750506308c379a06102805260206102a052601f19601f6102c051011660440161029cfd5b61024051614a835761020051815250614aec565b610220516102a0518082038281116159d05790509050614aa95761020051815250614aec565b61020051610220516102a0518082038281116159d057905090508082028115838383041417156159d057905090506102405180156159d057808204905090508152505b565b604051614b515760186080527f52656365697665722063616e6e6f74206265207a65726f2e000000000000000060a0526080506080518060a001601f825f031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6014546060518082018281106159d0579050905060145560156040516020525f5260405f2080546060518082018281106159d057905090508155506040515f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60605160805260206080a3606051815250565b6201224051614c6157602362017340527f43616e6e6f742073656e642073686172657320746f207a65726f20616464726562017360527f73732e0000000000000000000000000000000000000000000000000000000000620173805262017340506201734051806201736001601f825f031636823750506308c379a0620173005260206201732052601f19601f620173405101166044016201731cfd5b6020615d665f395f516370a08231620173405233620173605260206201734060246201735c845afa614c95573d5f5f3e3d5ffd5b60203d106159d0576201734090505162012220511115614d1d57601f62017380527f343632364465706f73697420696e73756666696369656e742066756e64732e00620173a0526201738050620173805180620173a001601f825f031636823750506308c379a0620173405260206201736052601f19601f620173805101166044016201735cfd5b614d2962017360611fe3565b62017360516201734052620122205161020052620173405161022052614d5162017380614878565b62017380516201736052620122605115614e0d57620122605162017360511015614e3457602a62017380527f4465706f73697420746f6f206c6f7720746f2072656365697665206d696e696d620173a0527f756d207368617265732e00000000000000000000000000000000000000000000620173c0526201738050620173805180620173a001601f825f031636823750506308c379a0620173405260206201736052601f19601f620173805101166044016201735cfd614e34565b62017360516040526201226051606052614e2962017380612067565b620173805162012260525b620122605161020052620173405161022052614e52620173a06149ae565b620173a05162017380526020615d665f395f516323b872dd620173a05233620173c05230620173e052620122205162017400526020620173a06064620173bc5f855af1614ea1573d5f5f3e3d5ffd5b3d614eb957803b156159d05760016201742052614ed4565b60203d106159d057620173a0518060011c6159d05762017420525b6201742050506001604052604036606037614eed612765565b5f61c44052620122205162017380518082038281116159d0579050905061c4605262012280515f81600581116159d0578015614f4f57905b6110208102620122a0016020815101611020830261c4a0018183825e505050600101818118614f25575b50508061c48052505f6201154052614f69620173c0612cc5565b620173c051620173a052614f7f620173e0611fe3565b620173e051620173c0526201734051620173c0511161502c57602b620173e0527f4552524f52202d206465706f73697420726573756c74656420696e206c6f737362017400527f206f6620617373657473210000000000000000000000000000000000000000006201742052620173e050620173e051806201740001601f825f031636823750506308c379a0620173a0526020620173c052601f19601f620173e0510116604401620173bcfd5b620173c05162017340518082038281116159d05790509050620173e052620173e0516102005262017340516102205261506762017420614878565b6201742051620174005262017360516201740051101561517c5762012260516201740051101561512557603962017420527f4552524f52202d20756e61626c6520746f206d656574206d696e696d756d207362017440527f6c69707061676520666f722074686973206465706f7369742100000000000000620174605262017420506201742051806201744001601f825f031636823750506308c379a0620173e05260206201740052601f19601f62017420510116604401620173fcfd5b620174005162017360526201224051337f9ffac2e4ff765185a768380c36a424716e6da986209dddf40813bc110c497187620122205162017420526201736051620174405262017360516201746052606062017420a35b6201224051604052620173605160605261519862017420614aee565b6201742050620173c05162017340518082038281116159d05790509050620174205260105462017420518082018281106159d057905090506010556201224051337fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d76201742051620174405262017360516201746052604062017440a3620173605181526201222051602082015250565b6201222051620173c05261523f62017380611fe3565b6201738051620173e0526040620173c06102005e61525f620173a0614878565b620173a05162017360526201736051601562012260516020525f5260405f2054101561531957602e62017380527f4f776e65722068617320696e61646571756174652073686172657320666f7220620173a0527f746869732077697468647261772e000000000000000000000000000000000000620173c0526201738050620173805180620173a001601f825f031636823750506308c379a0620173405260206201736052601f19601f620173805101166044016201735cfd5b62012260513314615417576201736051601662012260516020525f5260405f2080336020525f5260405f2090505410156153e157602d62017380527f4e6f7420617574686f72697a656420746f206d6f766520656e6f756768206f77620173a0527f6e65722773207368617265732e00000000000000000000000000000000000000620173c0526201738050620173805180620173a001601f825f031636823750506308c379a0620173405260206201736052601f19601f620173805101166044016201735cfd5b601662012260516020525f5260405f2080336020525f5260405f209050805462017360518082038281116159d057905090508155505b601562012260516020525f5260405f20805462017360518082038281116159d0579050905081555060145462017360518082038281116159d057905090506014555f62012260517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef62017360516201738052602062017380a3620122205161c44052620122805161c46052620122a0515f81600581116159d05780156154e357905b6110208102620122c0016020815101611020830261c4a0018183825e5050506001018181186154b9575b50508061c4805250600162011540526154fe620173a0612cc5565b620173a05162017380526201738051620122205111156155745762012260516201224051337fccee2505ffa87c9ac83adf384e5220eb5002aea81a8f925018510d483afbc13c6201222051620173a0526201736051620173c0526201738051620173e0526060620173a0a4620173805162012220525b6020615d665f395f5163a9059cbb620173a0526201224051620173c0526201222051620173e0526020620173a06044620173bc5f855af16155b7573d5f5f3e3d5ffd5b3d6155cf57803b156159d057600162017400526155ea565b60203d106159d057620173a0518060011c6159d05762017400525b6201740050506001604052604036606037615603612765565b60115462012220518082018281106159d0579050905060115562012260516201224051337ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db6201222051620173a0526201736051620173c0526040620173a0a4620173605181526201222051602082015250565b60805160156040516020525f5260405f2054101561570f57602260a0527f4552433230207472616e7366657220696e73756666696369656e742066756e6460c0527f732e00000000000000000000000000000000000000000000000000000000000060e05260a05060a0518060c001601f825f031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b60156040516020525f5260405f2080546080518082038281116159d0579050905081555060156060516020525f5260405f2080546080518082018281106159d057905090508155506060516040517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60805160a052602060a0a3565b60805160166040516020525f5260405f20806060516020525f5260405f209050556060516040517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560805160a052602060a0a3565b60a05160156060516020525f5260405f2054101561587957602660c0527f4552433230207472616e7366657246726f6d20696e73756666696369656e742060e0527f66756e64732e00000000000000000000000000000000000000000000000000006101005260c05060c0518060e001601f825f031636823750506308c379a0608052602060a052601f19601f60c0510116604401609cfd5b60156060516020525f5260405f20805460a0518082038281116159d0579050905081555060156080516020525f5260405f20805460a0518082018281106159d0579050905081555060a05160166060516020525f5260405f20806040516020525f5260405f20905054101561596957602660c0527f4552433230207472616e7366657220696e73756666696369656e7420616c6c6f60e0527f77616e63652e00000000000000000000000000000000000000000000000000006101005260c05060c0518060e001601f825f031636823750506308c379a0608052602060a052601f19601f60c0510116604401609cfd5b60166060516020525f5260405f20806040516020525f5260405f209050805460a0518082038281116159d057905090508155506080516060517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60a05160c052602060c0a3565b5f80fd00015b260400155aae0501515c4e07249b5ad60a00605ba60803f65a66090c475b460c00735be60800065c260548545a060c80d0e2750a58000506fdde030068000594bf804d0fce0045b68a6a670aa60005f40b817d036e0025bc157ac116220065095ea7b3192b00454a44f4cb0b92000523b872dd18e600656e553f6516150045a39a45b7023a0025bccabb7513a50005bc5c98b70678018538d52e0f01020005228bfd9f01650025b3d7f6b90f990025c8a872cb0aec000595d89b4100ae000518160ddd01c50005125151d701b900058da5cb5b0110000570a0823101d1002524fe17210b3c002505935a4f01a10005313ce56700f40005e134a7f704c90025e2c02ee5177b00c5a64fa59909ef0065b613ab9708150025f1e42ccd195c0045ef8b30f70f3c0025ce96cb77113c002521ab18870ca700250a28a477118d0025c55b0091015900055aa6e675011b000560a916d00127000501e1d1140a6a0005a2de9ae80dc200653f4ee62c08cf00c5b87b8a10163500a5e37074560cba00654ef501ac013300257d92535c089c0085870774120da20005736d8b6c146100a571f06c280a080085c1665ba00b9f00258d5a59380ab00025a10801600af60025320ad2ba0852004507a2d13a0edf00251d2ac68c01ad0005a318c1a417680085733272a0122800a5ba087652121d0065b460af94175b0065414e8486014d0005c6e6f5920eaa002596fee0600bb2006500c435030a7a0005af62a18f068301c5ae24a3a9019500055959397509e30045402d267d0f140025a9059cbb18b100458675c757142900453e1dcc7f141c002591dc418a143e00654cdad50611e80025a706bc840daf0025dd62ed3e01f70045c63d75b60f710025d905777e11c200252a068b460b32000525c4d9e8083e00251f55182a086f0065f94a7dfe0fd900858484ac7406230005d9c99c940c9a000584195c868b18321860184818281850182018601840184018281838190100a16576797065728300030a002b00000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000012000000000000000000000000fd03723a9a3abe0562451496a9a394d2c4bad4ab000000000000000000000000edf4b1a86320a7b635f4a5e90044c928a16c781a0000000000000000000000001904163120c9345c1b41c520481cc677768e944d00000000000000000000000000000000000000000000000000000004a817c80000000000000000000000000000000000000000000000000000000000000000144164617074657220536176696e6773204459414400000000000000000000000000000000000000000000000000000000000000000000000000000000000000057344594144000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x5f3560e01c60056005600a8306026159d401601b395f5160088160ff16838360181c0260181c0660031b8260081c61ffff1601601839505f51818160201c14600336111661004c57611ab8565b8061fffe163610348260011602176159d0578060101c61ffff16565b6020806040528060400160206020615ca65f395f510180615ca68339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b6020806040528060400160206020615d065f395f510180615d068339508051806020830101601f825f03163682375050601f19601f825160200101169050810190506040f35b6020615d4660403960206040f35b6020615d6660403960206040f35b5f5460405260206040f35b60015460405260206040f35b60025460405260206040f35b6004356003548110156159d0576004015460405260206040f35b600d5460405260206040f35b600e5460405260206040f35b6004358060a01c6159d057604052600f6040516020525f5260405f20805460605260018101546080525060406060f35b60105460405260206040f35b60115460405260206040f35b60125460405260206040f35b60135460405260206040f35b60145460405260206040f35b6004358060a01c6159d05760405260156040516020525f5260405f205460605260206060f35b6004358060a01c6159d0576040526024358060a01c6159d05760605260166040516020525f5260405f20806060516020525f5260405f2090505460805260206080f35b6004358060a01c6159d0576040525f543318156102d157602a6060527f4f6e6c79206578697374696e67206f776e65722063616e207265706c616365206080527f746865206f776e65722e0000000000000000000000000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b60405161033457601d6060527f4f776e65722063616e6e6f74206265206e756c6c20616464726573732e00000060805260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b5f546040517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c5f6060a36040515f55600160605260206060f35b6004358060a01c6159d0576040526001543318156104065760356060527f4f6e6c79206578697374696e6720476f7665726e616e636520636f6e747261636080527f74206d6179207265706c61636520697473656c662e000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b60405161048d5760226060527f476f7665726e616e63652063616e6e6f74206265206e756c6c206164647265736080527f732e00000000000000000000000000000000000000000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6001546040517f3aaaebeb4821d6a7e5c77ece53cff0afcc56c82add2c978dbbb7f73e84cbcfd25f6060a3604051600155600160605260206060f35b6004358060a01c6159d0576040525f543318156105605760346060527f4f6e6c79206f776e65722063616e206368616e6765207468652066756e6473206080527f616c6c6f636174696f6e20636f6e74726163742100000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6040516105e75760266060527f46756e6473416c6c6f6361746f722063616e6e6f74206265206e756c6c2061646080527f64726573732e000000000000000000000000000000000000000000000000000060a05260605060605180608001601f825f031636823750506308c379a06020526020604052601f19601f6060510116604401603cfd5b6002546040517f55b78759f76af43b8df65e695ca7be30a78c78d2717322edb8141fb5a02389bf5f6060a3604051600255600160605260206060f35b602080604052806040015f6003548083528060051b5f82600581116159d057801561066457905b80600401548160051b60208801015260010181811861064a575b505082016020019150509050810190506040f35b5f6201c960526106ec565b6101843560040160058135116159d05780355f81600581116159d05780156106e157905b8060051b60208501013560208501016110008135116159d057602081350161102083026201c98001818382375050506001018181186106a7575b5050806201c9605250505b6004358060a01c6159d0576201c800526024358060a01c6159d0576201c820526044356201c840526064358060a01c6159d0576201c860526084356201c8805260a4358060a01c6159d0576201c8a05260c4356201c8c05260e4358060a01c6159d0576201c8e052610104356201c90052610124358060a01c6159d0576201c92052610144356201c940526201c8005162017460526101406201c820620174805e61016435620175c0526201c960515f81600581116159d05780156107d857905b61102081026201c980016020815101611020830262017600018183825e5050506001018181186107ad575b505080620175e052506107ed62021a40613574565b62021a405162021a2052600160405260016060525f60805261080d612765565b602062021a20f35b6004358060a01c6159d057610560526020610560516104e052610839610580613bba565b610580f35b60016201750052606036620175203761095f565b6024358060011c6159d0576201750052606036620175203761095f565b6024358060011c6159d05762017500526044358060011c6159d0576201752052604036620175403761095f565b6024358060011c6159d05762017500526044358060011c6159d057620175205260643562017540525f620175605261095f565b6024358060011c6159d05762017500526044358060011c6159d0576201752052606435620175405260843560040160058135116159d05780355f81600581116159d057801561095457905b8060051b60208501013560208501016110008135116159d0576020813501611020830262017580018183823750505060010181811861091a575b505080620175605250505b6004358060a01c6159d057620174e0526020620174e051620122205262017560515f81600581116159d05780156109bd57905b611020810262017580016020815101611020830262012260018183825e505050600101818118610992575b505080620122405250606062017500620173005e6109dd6201c620613d5e565b6201c620f35b60403661068037610a1f565b6044358060011c6159d057610680525f6106a052610a1f565b6044358060011c6159d057610680526064356106a0525b6004358060a01c6159d057610640526024358060a01c6159d05761066052602060806106406104e05e610a536106c061443d565b6106c0f35b6020610a65610120611fe3565b610120f35b6020610a7660c0611abc565b60c0f35b610a85610140611abc565b610140516101205260206101205160c052610aa1610140611b6c565b610140f35b5f61020052610ab8565b600435610200525b604036610220376102005161012052610ad2610260611bf4565b610260805161022052602081015161024052506020610220f35b5f61020052610afe565b600435610200525b604036610220376102005161012052610b18610260611bf4565b610260805161022052602081015161024052506020610240f35b5f61020052610b44565b600435610200525b604036610220376102005161012052610b5e610260611bf4565b6102608051610220526020810151610240525061022051610240518082018281106159d05790509050610260526020610260f35b6040366201746037610c22565b60043562017460525f6201748052610c22565b600435620174605260243560040160058135116159d05780355f81600581116159d0578015610c1757905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174a00181838237505050600101818118610bdd575b505080620174805250505b6020600262012220526201746051620122405262017480515f81600581116159d0578015610c7757905b6110208102620174a0016020815101611020830262012280018183825e505050600101818118610c4c575b5050806201226052506040366201732037610c946201c540613133565b6201c540f35b6040366201746037610d2a565b60043562017460525f6201748052610d2a565b600435620174605260243560040160058135116159d05780355f81600581116159d0578015610d1f57905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174a00181838237505050600101818118610ce5575b505080620174805250505b6020600462012220526201746051620122405262017480515f81600581116159d0578015610d7f57905b6110208102620174a0016020815101611020830262012280018183825e505050600101818118610d54575b5050806201226052506040366201732037610d9c6201c540613133565b6201c540f35b6040366201746037610e32565b60043562017460525f6201748052610e32565b600435620174605260243560040160058135116159d05780355f81600581116159d0578015610e2757905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174a00181838237505050600101818118610ded575b505080620174805250505b6020600162012220526201746051620122405262017480515f81600581116159d0578015610e8757905b6110208102620174a0016020815101611020830262012280018183825e505050600101818118610e5c575b5050806201226052506040366201732037610ea46201c540613133565b6201c540f35b602060043561034052610ebe610300611abc565b610300516103605260406103406102005e610eda610320614878565b610320f35b602060043561034052610ef3610300611abc565b610300516103605260406103406102005e610f0f6103206149ae565b610320f35b6004358060a01c6159d0576040526f7fffffffffffffffffffffffffffffff60605260206060f35b602060043561034052610f50610300611abc565b610300516103605260406103406102005e610f6c610320614878565b610320f35b6004358060a01c6159d0576040526f7fffffffffffffffffffffffffffffff60605260206060f35b602060043561034052610fad610300611abc565b610300516103605260406103406102005e610fc96103206149ae565b610320f35b5f620174a052611041565b60443560040160058135116159d05780355f81600581116159d057801561103657905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174c00181838237505050600101818118610ffc575b505080620174a05250505b6024358060a01c6159d05762017480526004356201c5c0526110656201c580611fe3565b6201c580516201c5e05260406201c5c06102005e6110856201c5a06149ae565b6201c5a0516201c560526040366201c580376201c560516201222052620174805162012240525f6201226052620174a0515f81600581116159d05780156110f357905b6110208102620174c00160208151016110208302620122a0018183825e5050506001018181186110c8575b5050806201228052506111086201c5c0614bc4565b6201c5c080516201c5805260208101516201c5a05250600160405260016060525f608052611134612765565b60206201c5a0f35b6004358060a01c6159d0576103005260206015610300516020525f5260405f20546103605261116c610320611abc565b610320516103805260406103606102005e6111886103406149ae565b610340f35b6020600435610340526111a1610300611abc565b610300516103605260406103406102005e6111bd610320614878565b610320f35b6004358060a01c6159d05760405260156040516020525f5260405f205460605260206060f35b6020600435610340526111fc610300611abc565b610300516103605260406103406102005e6112186103206149ae565b610320f35b5f6201746052611290565b60643560040160058135116159d05780355f81600581116159d057801561128557905b8060051b60208501013560208501016110008135116159d0576020813501611020830262017480018183823750505060010181811861124b575b505080620174605250505b6024358060a01c6159d05762017420526044358060a01c6159d05762017440526004356201c580526112c46201c540611fe3565b6201c540516201c5a05260406201c5806102005e6112e46201c5606149ae565b6201c560516201c520526040366201c540376201c52051620122205262017420516201224052620174405162012260525f620122805262017460515f81600581116159d057801561135c57905b6110208102620174800160208151016110208302620122c0018183825e505050600101818118611331575b505080620122a052506113716201c580615229565b6201c58080516201c5405260208101516201c5605250600160405260016060525f60805261139d612765565b60206201c560f35b610560366106a0376113b8610c00612367565b610c0080516106a05260208101610500816106c05e50610520810151610bc052610540810151610be05250600160405260016060525f6080526113f9612765565b6106a051610c00526105006106c0610c205e6040610bc06111205e610560610c00f35b60603662012220376114e1565b602435620122205260403662012240376114e1565b60243562012220526044358060011c6159d05762012240525f62012260526114e1565b60243562012220526044358060011c6159d057620122405260643560040160058135116159d05780355f81600581116159d05780156114d657905b8060051b60208501013560208501016110008135116159d0576020813501611020830262012280018183823750505060010181811861149c575b505080620122605250505b5f5433181561157e57602362017320527f6f6e6c79206f776e65722063616e2063616c6c2062616c616e6365416461707462017340527f6572730000000000000000000000000000000000000000000000000000000000620173605262017320506201732051806201734001601f825f031636823750506308c379a0620172e05260206201730052601f19601f62017320510116604401620172fcfd5b60043561c44052620122205161c4605262012260515f81600581116159d05780156115cf57905b611020810262012280016020815101611020830261c4a0018183825e5050506001018181186115a5575b50508061c4805250620122405162011540526115ed62017340612cc5565b62017340516201732052600160405260016060525f60805261160d612765565b602062017320f35b604036620174a0376116a5565b604435620174a0525f620174c0526116a5565b604435620174a05260643560040160058135116159d05780355f81600581116159d057801561169a57905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174e00181838237505050600101818118611660575b505080620174c05250505b6024358060a01c6159d05762017480526040366201c580376004356201222052604062017480620122405e620174c0515f81600581116159d057801561171257905b6110208102620174e00160208151016110208302620122a0018183825e5050506001018181186116e7575b5050806201228052506117276201c5c0614bc4565b6201c5c080516201c5805260208101516201c5a05250600160405260016060525f608052611753612765565b60206201c580f35b60403662017460376117eb565b60643562017460525f62017480526117eb565b606435620174605260843560040160058135116159d05780355f81600581116159d05780156117e057905b8060051b60208501013560208501016110008135116159d05760208135016110208302620174a001818382375050506001018181186117a6575b505080620174805250505b6024358060a01c6159d05762017420526044358060a01c6159d05762017440526040366201c540376004356201222052606062017420620122405e62017480515f81600581116159d057801561186857905b6110208102620174a00160208151016110208302620122c0018183825e50505060010181811861183d575b505080620122a0525061187d6201c580615229565b6201c58080516201c5405260208101516201c5605250600160405260016060525f6080526118a9612765565b60206201c540f35b6004358060a01c6159d0576101005233604052610100516060526024356080526118d9615677565b6001610120526020610120f35b6004358060a01c6159d057610120526024358060a01c6159d0576101405233604052604061012060605e60443560a05261191e6157e0565b6001610160526020610160f35b6004358060a01c6159d05760c0523360405260c05160605260243560805261195161578b565b600160e052602060e0f35b6004358060a01c6159d0576040526024358060a01c6159d0576060525f543318156119dd57601c6080527f4f6e6c79206f776e65722063616e20636c61696d52657761726473210000000060a0526080506080518060a001601f825f031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6040515f6080525f600354600581116159d0578015611a1857905b80600401548318611a0d576001608052611a18565b6001018181186119f8575b50506080519050611a7f57601360a0527f4e6f7420612076616c696420616461707465720000000000000000000000000060c05260a05060a0518060c001601f825f031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b6040515a63ef5cfb8c608452600460605160a4526020016080526080505f5f60805160a08585f490509050611ab6573d5f5f3e3d5ffd5b005b5f5ffd5b6020615d665f395f516370a0823160605230608052602060606024607c845afa611ae8573d5f5f3e3d5ffd5b60203d106159d05760609050516040525f600354600581116159d0578015611b6257905b80600401546060526040516060516301e1d114608052602060806004609c845afa611b39573d5f5f3e3d5ffd5b60203d106159d05760809050518082018281106159d05790509050604052600101818118611b0c575b5050604051815250565b60c05160e05260e051611b8c57611b84610100611abc565b6101005160e0525b60115460e0518082018281106159d057905090506012548082018281106159d057905090506013548082018281106159d057905090508060ff1c6159d0576010548060ff1c6159d0578082038281135f8312186159d057905090506101005261010051815250565b610120516101405261014051611c1857611c0f610160611abc565b61016051610140525b6101405160c052611c2a610180611b6c565b61018051610160525f6101605113611c4b575f81525f602082015250611cf8565b60403661018037610160515f81126159d0578060011b818160011c186159d05790506064810490506101c052610160515f81126159d0576001811517156159d0575f90506064810490506101e0526101c0516012541015611cc0576101c0516012548082038281116159d05790509050610180525b6101e0516013541015611ce7576101e0516013548082038281116159d057905090506101a0525b6101805181526101a0516020820152505b565b604036610260376102405161012052611d146102a0611bf4565b6102a08051610260526020810151610280525060026102005118611d38575f610280525b60046102005118611d49575f610260525b600d54611d56575f610260525b60026102005118611d68576001611d71565b60016102005118155b611d7b575f611d81565b5f543314155b15611d8c575f610260525b60046102005118611d9e576001611da7565b60016102005118155b15611e5157600d543318611dbc576001611dc3565b6001543318155b611e5157603b6102a0527f4f6e6c7920637572656e742070726f706f736572206f7220676f7665726e616e6102c0527f6365206d617920636c61696d20737472617465677920666565732e00000000006102e0526102a0506102a051806102c001601f825f031636823750506308c379a061026052602061028052601f19601f6102a051011660440161027cfd5b61026051610280518082018281106159d05790509050610220511115611efb57602c6102a0527f4e6f7420656e6f756768206665657320746f2066756c66696c6c2072657175656102c0527f7374656420616d6f756e742e00000000000000000000000000000000000000006102e0526102a0506102a051806102c001601f825f031636823750506308c379a061026052602061028052601f19601f6102a051011660440161027cfd5b61026051815261028051602082015250565b600a5c611f55576020615d665f395f516370a0823160405230606052602060406024605c845afa611f40573d5f5f3e3d5ffd5b60203d106159d0576040905051600a5d5f600c5d5b600a5c815250565b604051611f6d575f815250611fe1565b600b6040516020525f5260405f205c60605260605115611f9257606051815250611fe1565b6040516301e1d114608052602060806004609c845afa611fb4573d5f5f3e3d5ffd5b60203d106159d0576080905051606052606051600b6040516020525f5260405f205d5f600c5d6060518152505b565b600c5c15611ff657600c5c815250612065565b61200060e0611f0d565b60e05160c0525f600354600581116159d057801561205657905b806004015460e05260c05160e051604052612036610100611f5d565b610100518082018281106159d0579050905060c05260010181811861201a575b505060c051600c5d60c0518152505b565b606051608052606051612111576040516402540be4007036f9bfb3af7b756fad5cd10396a21346cb82116159d057810290506020615c865f395f5164e8d4a510006402540be4008202058060140b81186159d05790508082028115838383051417156159d0576402540be40081058060140b81186159d0579050905090506402540be4005f82126159d0578105905060a05260405160a0518082038281116159d057905090506080525b608051604051101561219d57603260a0527f44657369726564206173736574732063616e6e6f74206265206c65737320746860c0527f616e206d696e696d756d2061737365747321000000000000000000000000000060e05260a05060a0518060c001601f825f031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b608051815250565b610120516121d6576121b8610160611fe3565b61016051610140518082038281116159d05790509050815250612228565b604061012060405e6121e9610160612067565b61016051610140526121fc610160611fe3565b6101605161012051610140518082038281116159d057905090508082038281116159d057905090508152505b565b60405163ac7a1b5b608052602060806004609c845afa61224c573d5f5f3e3d5ffd5b60203d106159d05760809050516060527f8000000000000000000000000000000000000000000000000000000000000000606051106122aa577f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6060525b6060518060ff1c6159d057805f03600160ff1b82141582825f031416156159d0579050815250565b604051636083e59a608052602060806004609c845afa6122f4573d5f5f3e3d5ffd5b60203d106159d05760809050516060527f800000000000000000000000000000000000000000000000000000000000000060605110612356577f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff815250612365565b6060518060ff1c6159d0578152505b565b61237160e0611f0d565b60e05160c0526105003660e0376003546123ac5760c05181526020810161050060e0825e5060c0516105208201525f61054082015250612566565b60c0516105e052604036610600375f600354600581116159d057801561253d57905b8060040154610640526106405161062051600481116159d05760081b60e0015261064051604052612400610660611f5d565b6106605161062051600481116159d05760081b60e001602081019050526105e05161062051600481116159d05760081b60e001602081019050518082018281106159d057905090506105e0526106405160405261245e61066061222a565b6106605161062051600481116159d05760081b60e001608081019050526106405160405261248d6106606122d2565b6106605161062051600481116159d05760081b60e00160608101905052600f610640516020525f5260405f20805461066052600181015461068052506106605161062051600481116159d05760081b60e00160a0810190505261060051610660518082018281106159d05790509050610600526106805161062051600481116159d05760081b60e0016040810190505261062051600181018181106159d0579050610620526001018181186123ce575b505060c05181526020810161050060e0825e506105e05161052082015261060051610540820152505b565b6020615d665f395f516370a082316106005230610620526020610600602461061c845afa612598573d5f5f3e3d5ffd5b60203d106159d0576106009050516105e052600254633c64f7d8610600526105e0516106205260405161064052606060606106605e61050060c06106c05e6105c051610bc0526101e06106006105c461061c845afa6125f9573d5f5f3e3d5ffd5b6101e03d106159d05761060051610be052610620518060a01c6159d057610c005261064051610c2052610660518060a01c6159d057610c405261068051610c60526106a0518060a01c6159d057610c80526106c051610ca0526106e0518060a01c6159d057610cc05261070051610ce052610720518060a01c6159d057610d0052610740518060a01c6159d057610d2052610760518060a01c6159d057610d4052610780518060a01c6159d057610d60526107a0518060a01c6159d057610d80526107c0518060a01c6159d057610da052610be090506101e081835e5050565b6003546040511861275e575f615120525f600354600581116159d057801561275b57905b80600401546151405261514051615100511861273b57611020615120516040518110156159d0570260600160208151018082865e5050505050612763565b61512051600181018181106159d0579050615120526001018181186126fd575b50505b5f8152505b565b5f600c5d60405115612776575f600a5d5b606051156127d4576080516127c3575f600354600581116159d05780156127bc57905b806004015460a0525f600b60a0516020525f5260405f205d600101818118612799575b50506127d4565b5f600b6080516020525f5260405f205d5b565b6151a0515f81600581116159d057801561281457905b61102081026151c001602081510161102083026060018183825e5050506001018181186127ec575b50508060405250615160516151005261282e61b2806126d9565b61b2806020815101808261a2605e50505f61b280526151605160405261285561b2e0611f5d565b61b2e05161b2c052615160515a635d30351961b2e452600460406151805161b304528061b324528061b30401602061a26051018061a260835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190500161b2e05261b2e050602061c3a061b2e05161b3008585f4905090506128dc573d5f5f3e3d5ffd5b3d602081183d602010021861c3805261c3806020815101808261b2805e50506001604052600160605261516051608052612914612765565b6151605160405261292661b300611f5d565b61b3005161b2e05261b2e051600f615160516020525f5260405f2060018101905055565b6151c0515f81600581116159d057801561298857905b61102081026151e001602081510161102083026060018183825e505050600101818118612960575b5050806040525061516051615100526129a261b2c06126d9565b61b2c06020815101808261a2a05e50506020615d665f395f516370a0823161b2e0526151a05161b30052602061b2e0602461b2fc845afa6129e5573d5f5f3e3d5ffd5b60203d106159d05761b2e090505161b2c0525f61b2e052600161b3205261516051612a6f57600e61b340527f454d50545920414441505445522100000000000000000000000000000000000061b3605261b3405061b340518061b36001601f825f031636823750506308c379a061b30052602061b32052601f19601f61b34051011660440161b31cfd5b6151a051612adc57601261b340527f454d5054592057495448445241575f544f21000000000000000000000000000061b3605261b3405061b340518061b36001601f825f031636823750506308c379a061b30052602061b32052601f19601f61b34051011660440161b31cfd5b61a28051612b8857615160515a6362b2b5f061b3445260046060604061518061b3645e8061b3a4528061b36401602061a2a051018061a2a0835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190500161b3405261b34050602061c42061b3405161b3608585f490509050612b64573d5f5f3e3d5ffd5b3d602081183d602010021861c4005261c4006020815101808261b2e05e5050612c20565b615160515a6362b2b5f061b3445260046060604061518061b3645e8061b3a4528061b36401602061a2a051018061a2a0835e508051806020830101601f825f03163682375050601f19601f825160200101169050810190500161b3405261b34050602061c42061b3405161b3608585f49050905061b320523d602081183d602010021861c4005261c4006020815101808261b2e05e50505b6001604052600160605261516051608052612c39612765565b6020615d665f395f516370a0823161b360526151a05161b38052602061b360602461b37c845afa612c6c573d5f5f3e3d5ffd5b60203d106159d05761b36090505161b3405261516051604052612c9061b360611f5d565b61b36051600f615160516020525f5260405f206001810190505561b3405161b2c0518082038281116159d05790509050815250565b6101e0366201156037604061c4406101205e612ce3620117606121a5565b62011760516201174052600354612d3f576020615d665f395f516370a08231620117605230620117805260206201176060246201177c845afa612d28573d5f5f3e3d5ffd5b60203d106159d05762011760905051815250613131565b610560366201176037612d5462011cc0612367565b62011cc0805162011760526020810161050081620117805e5061052081015162011c805261054081015162011ca0525061c44051604052600e54606052604062011c8060805e6105006201178060c05e62011540516105c052612db962011cc0612568565b62011cc061014081620115605e610140810160a081620116a05e50505f6005905b8060051b620116a0015162011cc05262011cc051612df757612ed2565b600f62011cc0516020525f5260405f20805462011ce052600181015462011d0052505f62011ce052600f62011cc0516020525f5260405f2062011ce051815562011d005160018201555062011cc051604052612e5562011d40611f5d565b62011d405162011d2052620117405162011d005162011d20518082038281116159d057905090508082038281116159d05790509050620117405262011cc0517f8af0bf5fccd11158fcb7ce9747ad88f3bc6f4c3d21019bc157b1fea3f052ddcc604062011d0062011d405e604062011d40a2600101818118612dda575b50505f6005905b8060061b620115600160408162011cc05e5062011ce051612ef95761307a565b62011cc051612f075761306f565b600e548060ff1c6159d05762011cc0511215612fe7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff62011cc0511361306f5762011cc051805f03600160ff1b82141582825f031416156159d05790505f81126159d05762011d0052604062011ce06151605e306151a05261c480515f81600581116159d0578015612fbf57905b611020810261c4a001602081510161102083026151e0018183825e505050600101818118612f96575b5050806151c052505f61a28052612fd862011d4061294a565b62011d405162011d205261306f565b62011cc0515f81126159d057612fff62011d20611f0d565b62011d20518082811882841002189050905062011d0052604062011ce06151605e61c480515f81600581116159d057801561305f57905b611020810261c4a001602081510161102083026151c0018183825e505050600101818118613036575b5050806151a0525061306f6127d6565b600101818118612ed9575b505061308862011ce0611fe3565b62011ce05162011cc05262011740516130a362011ce0611fe3565b62011ce051101561311c57601262011d00527f536c69707061676520657863656564656421000000000000000000000000000062011d205262011d005062011d00518062011d2001601f825f031636823750506308c379a062011cc052602062011ce052601f19601f62011d0051011660440162011cdcfd5b61312862011ce0611f0d565b62011ce0518152505b565b60403662017360376040620122206102005e62017320516102405261315a620173a0611cfa565b620173a0805162017360526020810151620173805250620173605162017380518082018281106159d05790509050620173a0526201224051156131a2576201224051620173a0525b6131ae620173e0611f0d565b620173e051620173c052620173a051620173c051106131e857620173a051620173c05180828118828410021890509050620173a052613273565b620173a05161c44052620173405161c4605262012260515f81600581116159d057801561323b57905b611020810262012280016020815101611020830261c4a0018183825e505050600101818118613211575b50508061c480525060016201154052613256620173e0612cc5565b620173e051620173a05180828118828410021890509050620173a0525b620173805115613289576201736051151561328b565b5f5b6132b7576201738051156132a857620173a05162017380526133b9565b620173a05162017360526133b9565b62017380516402540be4007036f9bfb3af7b756fad5cd10396a21346cb82116159d05781029050620173805162017360518082018281106159d057905090506402540be4007036f9bfb3af7b756fad5cd10396a21346cb82116159d0578102905080156159d057806402540be4008302058060140b81186159d05790509050620173a0516402540be4007036f9bfb3af7b756fad5cd10396a21346cb82116159d057810290508082028115838383051417156159d0576402540be40081058060140b81186159d0579050905090506402540be4005f82126159d057810590506201738052620173a05162017380518082038281116159d0579050905062017360525b60125462017360518082018281106159d0579050905060125560135462017380518082018281106159d0579050905060135562017380511561340157600d545f541415613403565b5f5b156134aa57600d543318613418576001613423565b600e54620173805110155b156134a3576020615d665f395f5163a9059cbb620173e052600d546201740052620173805162017420526020620173e06044620173fc5f855af1613469573d5f5f3e3d5ffd5b3d61348157803b156159d0576001620174405261349c565b60203d106159d057620173e0518060011c6159d05762017440525b6201744050505b5f62017380525b620173605162017380518082018281106159d0579050905015613554576020615d665f395f5163a9059cbb620173e0525f546201740052620173605162017380518082018281106159d0579050905062017420526020620173e06044620173fc5f855af161351a573d5f5f3e3d5ffd5b3d61353257803b156159d0576001620174405261354d565b60203d106159d057620173e0518060011c6159d05762017440525b6201744050505b600160405260016060525f60805261356a612765565b620173a051815250565b60015433181561361257602b6201c6a0527f4f6e6c7920476f7665726e616e63652044414f206d6179207365742061206e656201c6c0527f772073747261746567792e0000000000000000000000000000000000000000006201c6e0526201c6a0506201c6a051806201c6c001601f825f031636823750506308c379a06201c6605260206201c68052601f19601f6201c6a05101166044016201c67cfd5b620174605161368957601f6201c6a0527f50726f706f7365722063616e2774206265206e756c6c20616464726573732e006201c6c0526201c6a0506201c6a051806201c6c001601f825f031636823750506308c379a06201c6605260206201c68052601f19601f6201c6a05101166044016201c67cfd5b6201746051600d5414613778576136a26201c6c0611abc565b6201c6c0516201c6a0526040366201c6c0376201c6a051610120526136c96201c700611bf4565b6201c70080516201c6c05260208101516201c6e05250600e546201c6e051111561376757600462012220525f6201224052620175e0515f81600581116159d057801561373c57905b611020810262017600016020815101611020830262012280018183825e505050600101818118613711575b5050806201226052506201c6a05162017320525f62017340526137616201c700613133565b6201c700505b6201746051600d55620175c051600e555b5f600354600581116159d05780156137b357905b80600401546201c6a0525f600f6201c6a0516020525f5260405f205560010181811861378c575b50505f6005905b8060061b62017480016040816201c6a05e506040366201c6e0376201c6c0516201c6e052600f6201c6a0516020525f5260405f20600181019050546201c70052600f6201c6a0516020525f5260405f206201c6e05181556201c700516001820155506001018181186137ba5750507f357e53e5fd1ca670f6f6f6174e30cb36eda3d81b8ca610e6cc90668610c810f4610140620174806201c6a05e62017460516201c7e0526101606201c6a0a16001815250565b604051156139d55760405163ed2127186101e0526101806101e060046101fc845afa61389c573d5f5f3e3d5ffd5b60403d106159d0576101e0516101e001600a8151116159d05780515f81600a81116159d05780156138ef57905b8060051b6020850101518060a01c6159d0578160051b6103a001526001018181186138c9575b5050806103805250506103809050805160208160051b01808360805e5050505f608051600a81116159d05780156139d257905b8060051b60a001516101e05260096101e0516020525f5260405f2054610200526060516102005118156139b457601e610220527f696e636f6d696e6720746f6b656e20616c72656164792068616e646c656400006102405261022050610220518061024001601f825f031636823750506308c379a06101e052602061020052601f19601f6102205101166044016101fcfd5b60405160096101e0516020525f5260405f2055600101818118613922575b50505b60605115613bb85760605163ed2127186101e0526101806101e060046101fc845afa613a03573d5f5f3e3d5ffd5b60403d106159d0576101e0516101e001600a8151116159d05780515f81600a81116159d0578015613a5657905b8060051b6020850101518060a01c6159d0578160051b6103a00152600101818118613a30575b5050806103805250506103809050805160208160051b01808360805e5050505f608051600a81116159d0578015613bb557905b8060051b60a001516101e05260096101e0516020525f5260405f205461020052604051613b3857606051610200511815613b2257601e610220527f6f7574676f696e6720746f6b656e20616c72656164792068616e646c656400006102405261022050610220518061024001601f825f031636823750506308c379a06101e052602061020052601f19601f6102205101166044016101fcfd5b5f60096101e0516020525f5260405f2055613baa565b604051610200511815613baa57601e610220527f6f7574676f696e6720746f6b656e20616c72656164792068616e646c656400006102405261022050610220518061024001601f825f031636823750506308c379a06101e052602061020052601f19601f6102205101166044016101fcfd5b600101818118613a89575b50505b565b5f54331815613c4d576028610500527f4f6e6c79206f776e65722063616e20616464206e6577204c656e64696e672041610520527f646170746572732e0000000000000000000000000000000000000000000000006105405261050050610500518061052001601f825f031636823750506308c379a06104c05260206104e052601f19601f6105005101166044016104dcfd5b6104e0515f610500525f600354600581116159d0578015613c8b57905b80600401548318613c8057600161050052613c8b565b600101818118613c6a575b505061050051905015613cfd57601a610520527f6164617074657220616c726561647920737570706f727465642e0000000000006105405261052050610520518061054001601f825f031636823750506308c379a06104e052602061050052601f19601f6105205101166044016104fcfd5b600354600481116159d0576104e051816004015560018101600355506104e0516040525f606052613d2c61386e565b6104e051337f4b3749a16ab97cf0e9866299c183369da7570769bb78bd2c62a7df5c8da426315f610500a36001815250565b5f54331815613dfb57602762017360527f4f6e6c79206f776e65722063616e2072656d6f7665204c656e64696e6720416462017380527f6170746572732e00000000000000000000000000000000000000000000000000620173a05262017360506201736051806201738001601f825f031636823750506308c379a0620173205260206201734052601f19601f620173605101166044016201733cfd5b6201222051600162017360525f600354600581116159d0578015613e3c57905b80600401548318613e31575f6201736052613e3c565b600101818118613e1b575b50506201736051905015613e53575f81525061443b565b6201222051604052613e6762017380611f5d565b6201738051620173605262017360516040526201734051606052613e8d620173a0612067565b620173a0516201738052620173605162017380518082038281116159d05790509050620173a0525f600f62012220516020525f5260405f2055600162017300511861413a57613ede620173e0611fe3565b620173e051620173c0525f61c44052620173a05161c4605262012240515f81600581116159d0578015613f3757905b611020810262012260016020815101611020830261c4a0018183825e505050600101818118613f0d575b50508061c48052505f6201154052613f51620173e0612cc5565b620173e050620173205161432257613f6b62017400611fe3565b6201740051620173e052620173c051620173e051101561432257620173c051620173e0518082038281116159d05790509050620174005262017400516201736051101561406c57605062017420527f4552524f52202d206c6f7373207761732067726561746572207468616e20616462017440527f6170746572206173736574732e2054727920746f2072656d6f7665207769746862017460527f6f757420726562616c616e63696e672e00000000000000000000000000000000620174805262017420506201742051806201744001601f825f031636823750506308c379a0620173e05260206201740052601f19601f62017420510116604401620173fcfd5b6201740051620173a051101561432257604e62017420527f4552524f52202d20746f6f206d75636820736c6970706167652072656d6f766962017440527f6e6720616461707465722e2054727920746f2072656d6f766520776974686f7562017460527f7420726562616c616e63696e672e000000000000000000000000000000000000620174805262017420506201742051806201744001601f825f031636823750506308c379a0620173e05260206201740052601f19601f62017420510116604401620173fcfd614322565b62017360511561432257620122205161516052620173605161518052306151a05262012240515f81600581116159d057801561419c57905b61102081026201226001602081510161102083026151e0018183825e505050600101818118614172575b5050806151c05250620173205161a280526141b9620173e061294a565b620173e051620173c05262017320516143225762012220516040526141e0620173e0611f5d565b620173e0511561427e57603762017400527f4552524f52202d2061646170746572206164617074657220746f20626520726562017420527f6d6f766564207374696c6c206861732061737365747321000000000000000000620174405262017400506201740051806201742001601f825f031636823750506308c379a0620173c0526020620173e052601f19601f62017400510116604401620173dcfd5b620173c0516201738051111561432257602e620173e0527f4552524f52202d20746f6f206d75636820736c697070616765206f6e2061646162017400527f707465722077697468647261772e0000000000000000000000000000000000006201742052620173e050620173e051806201740001601f825f031636823750506308c379a0620173a0526020620173c052601f19601f620173e0510116604401620173bcfd5b5f620173c0525f600354600581116159d057801561438757905b80600401546201748052620122205162017480511461437c57620173c051600481116159d05762017480518160051b620173e0015260018101620173c052505b60010181811861433c575b5050620173c05160208160051b015f81601f0160051c600681116159d05780156143c757905b8060051b620173c0015181600301556001018181186143ad575b505050505f60405262012220516060526143df61386e565b6201222051337f25a12528a39d56c4ad0183f3bbb17f4d36cb1bcf8f360da144ad4fd321f78eae620122205160405261441a62017480611f5d565b6201748051620174a0526201732051620174c0526040620174a0a360018152505b565b5f543318156144d0576025610560527f4f6e6c79206f776e65722063616e2073776170204c656e64696e672041646170610580527f746572732e0000000000000000000000000000000000000000000000000000006105a05261056050610560518061058001601f825f031636823750506308c379a061052052602061054052601f19601f61056051011660440161053cfd5b6104e051156144e4576105005115156144e6565b5f5b614574576025610560527f43616e2774206861766520656d707479206164647265737320666f7220616461610580527f707465722e0000000000000000000000000000000000000000000000000000006105a05261056050610560518061058001601f825f031636823750506308c379a061052052602061054052601f19601f61056051011660440161053cfd5b6104e051604052614586610580611f5d565b6105805161056052610500516040526145a06105a0611f5d565b6105a05161058052610520516145bb576105605115156145bd565b5f5b1561468957610560516105805110156146895761056051604052610540516060526145e96105c0612067565b6105c0516105a052610580516105a05111156146895760266105c0527f4552524f52202d20537761702065786365656473206d6178696d756d20736c696105e0527f70706167652e0000000000000000000000000000000000000000000000000000610600526105c0506105c051806105e001601f825f031636823750506308c379a06105805260206105a052601f19601f6105c051011660440161059cfd5b6040366105a0375f600354600581116159d05780156146e557905b80600401546105e0526104e0516105e051186146c55760016105c0526146e5565b6105a051600181018181106159d05790506105a0526001018181186146a4575b50506105c0516147795760256105e0527f4164617074657220746f206265207265706c6163656420776173206e6f742066610600527f6f756e642e000000000000000000000000000000000000000000000000000000610620526105e0506105e0518061060001601f825f031636823750506308c379a06105a05260206105c052601f19601f6105e05101166044016105bcfd5b610500516105a0516003548110156159d05760040155600f6104e0516020525f5260405f2054600f610500516020525f5260405f205561058051600f610500516020525f5260405f2060018101905055600f6104e0516020525f5260405f205f81555f600182015550610500516040526104e0516060526147f861386e565b6104e051337f25a12528a39d56c4ad0183f3bbb17f4d36cb1bcf8f360da144ad4fd321f78eae6104e0516040526148306105e0611f5d565b6105e0516106005261052051610620526040610600a361050051337f4b3749a16ab97cf0e9866299c183369da7570769bb78bd2c62a7df5c8da426315f6105e0a36001815250565b601454610240526040366102603761022051610120526148996102a0611bf4565b6102a08051610260526020810151610280525061026051610280518082018281106159d057905090506102a052610240516148da57610200518152506149ac565b610220516148ee57610200518152506149ac565b6102a0516102205110156149615760206102c0527f5f636f6e76657274546f5368617265732073616e697479206661696c757265216102e0526102c0506102c051806102e001601f825f031636823750506308c379a06102805260206102a052601f19601f6102c051011660440161029cfd5b610220516102a0518082038281116159d057905090506102c05261020051610240518082028115838383041417156159d057905090506102c05180156159d057808204905090508152505b565b601454610240526040366102603761022051610120526149cf6102a0611bf4565b6102a08051610260526020810151610280525061026051610280518082018281106159d057905090506102a0526102a051610220511015614a6f5760206102c0527f5f636f6e76657274546f4173736574732073616e697479206661696c757265216102e0526102c0506102c051806102e001601f825f031636823750506308c379a06102805260206102a052601f19601f6102c051011660440161029cfd5b61024051614a835761020051815250614aec565b610220516102a0518082038281116159d05790509050614aa95761020051815250614aec565b61020051610220516102a0518082038281116159d057905090508082028115838383041417156159d057905090506102405180156159d057808204905090508152505b565b604051614b515760186080527f52656365697665722063616e6e6f74206265207a65726f2e000000000000000060a0526080506080518060a001601f825f031636823750506308c379a06040526020606052601f19601f6080510116604401605cfd5b6014546060518082018281106159d0579050905060145560156040516020525f5260405f2080546060518082018281106159d057905090508155506040515f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60605160805260206080a3606051815250565b6201224051614c6157602362017340527f43616e6e6f742073656e642073686172657320746f207a65726f20616464726562017360527f73732e0000000000000000000000000000000000000000000000000000000000620173805262017340506201734051806201736001601f825f031636823750506308c379a0620173005260206201732052601f19601f620173405101166044016201731cfd5b6020615d665f395f516370a08231620173405233620173605260206201734060246201735c845afa614c95573d5f5f3e3d5ffd5b60203d106159d0576201734090505162012220511115614d1d57601f62017380527f343632364465706f73697420696e73756666696369656e742066756e64732e00620173a0526201738050620173805180620173a001601f825f031636823750506308c379a0620173405260206201736052601f19601f620173805101166044016201735cfd5b614d2962017360611fe3565b62017360516201734052620122205161020052620173405161022052614d5162017380614878565b62017380516201736052620122605115614e0d57620122605162017360511015614e3457602a62017380527f4465706f73697420746f6f206c6f7720746f2072656365697665206d696e696d620173a0527f756d207368617265732e00000000000000000000000000000000000000000000620173c0526201738050620173805180620173a001601f825f031636823750506308c379a0620173405260206201736052601f19601f620173805101166044016201735cfd614e34565b62017360516040526201226051606052614e2962017380612067565b620173805162012260525b620122605161020052620173405161022052614e52620173a06149ae565b620173a05162017380526020615d665f395f516323b872dd620173a05233620173c05230620173e052620122205162017400526020620173a06064620173bc5f855af1614ea1573d5f5f3e3d5ffd5b3d614eb957803b156159d05760016201742052614ed4565b60203d106159d057620173a0518060011c6159d05762017420525b6201742050506001604052604036606037614eed612765565b5f61c44052620122205162017380518082038281116159d0579050905061c4605262012280515f81600581116159d0578015614f4f57905b6110208102620122a0016020815101611020830261c4a0018183825e505050600101818118614f25575b50508061c48052505f6201154052614f69620173c0612cc5565b620173c051620173a052614f7f620173e0611fe3565b620173e051620173c0526201734051620173c0511161502c57602b620173e0527f4552524f52202d206465706f73697420726573756c74656420696e206c6f737362017400527f206f6620617373657473210000000000000000000000000000000000000000006201742052620173e050620173e051806201740001601f825f031636823750506308c379a0620173a0526020620173c052601f19601f620173e0510116604401620173bcfd5b620173c05162017340518082038281116159d05790509050620173e052620173e0516102005262017340516102205261506762017420614878565b6201742051620174005262017360516201740051101561517c5762012260516201740051101561512557603962017420527f4552524f52202d20756e61626c6520746f206d656574206d696e696d756d207362017440527f6c69707061676520666f722074686973206465706f7369742100000000000000620174605262017420506201742051806201744001601f825f031636823750506308c379a0620173e05260206201740052601f19601f62017420510116604401620173fcfd5b620174005162017360526201224051337f9ffac2e4ff765185a768380c36a424716e6da986209dddf40813bc110c497187620122205162017420526201736051620174405262017360516201746052606062017420a35b6201224051604052620173605160605261519862017420614aee565b6201742050620173c05162017340518082038281116159d05790509050620174205260105462017420518082018281106159d057905090506010556201224051337fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d76201742051620174405262017360516201746052604062017440a3620173605181526201222051602082015250565b6201222051620173c05261523f62017380611fe3565b6201738051620173e0526040620173c06102005e61525f620173a0614878565b620173a05162017360526201736051601562012260516020525f5260405f2054101561531957602e62017380527f4f776e65722068617320696e61646571756174652073686172657320666f7220620173a0527f746869732077697468647261772e000000000000000000000000000000000000620173c0526201738050620173805180620173a001601f825f031636823750506308c379a0620173405260206201736052601f19601f620173805101166044016201735cfd5b62012260513314615417576201736051601662012260516020525f5260405f2080336020525f5260405f2090505410156153e157602d62017380527f4e6f7420617574686f72697a656420746f206d6f766520656e6f756768206f77620173a0527f6e65722773207368617265732e00000000000000000000000000000000000000620173c0526201738050620173805180620173a001601f825f031636823750506308c379a0620173405260206201736052601f19601f620173805101166044016201735cfd5b601662012260516020525f5260405f2080336020525f5260405f209050805462017360518082038281116159d057905090508155505b601562012260516020525f5260405f20805462017360518082038281116159d0579050905081555060145462017360518082038281116159d057905090506014555f62012260517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef62017360516201738052602062017380a3620122205161c44052620122805161c46052620122a0515f81600581116159d05780156154e357905b6110208102620122c0016020815101611020830261c4a0018183825e5050506001018181186154b9575b50508061c4805250600162011540526154fe620173a0612cc5565b620173a05162017380526201738051620122205111156155745762012260516201224051337fccee2505ffa87c9ac83adf384e5220eb5002aea81a8f925018510d483afbc13c6201222051620173a0526201736051620173c0526201738051620173e0526060620173a0a4620173805162012220525b6020615d665f395f5163a9059cbb620173a0526201224051620173c0526201222051620173e0526020620173a06044620173bc5f855af16155b7573d5f5f3e3d5ffd5b3d6155cf57803b156159d057600162017400526155ea565b60203d106159d057620173a0518060011c6159d05762017400525b6201740050506001604052604036606037615603612765565b60115462012220518082018281106159d0579050905060115562012260516201224051337ffbde797d201c681b91056529119e0b02407c7bb96a4a2c75c01fc9667232c8db6201222051620173a0526201736051620173c0526040620173a0a4620173605181526201222051602082015250565b60805160156040516020525f5260405f2054101561570f57602260a0527f4552433230207472616e7366657220696e73756666696369656e742066756e6460c0527f732e00000000000000000000000000000000000000000000000000000000000060e05260a05060a0518060c001601f825f031636823750506308c379a06060526020608052601f19601f60a0510116604401607cfd5b60156040516020525f5260405f2080546080518082038281116159d0579050905081555060156060516020525f5260405f2080546080518082018281106159d057905090508155506060516040517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60805160a052602060a0a3565b60805160166040516020525f5260405f20806060516020525f5260405f209050556060516040517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560805160a052602060a0a3565b60a05160156060516020525f5260405f2054101561587957602660c0527f4552433230207472616e7366657246726f6d20696e73756666696369656e742060e0527f66756e64732e00000000000000000000000000000000000000000000000000006101005260c05060c0518060e001601f825f031636823750506308c379a0608052602060a052601f19601f60c0510116604401609cfd5b60156060516020525f5260405f20805460a0518082038281116159d0579050905081555060156080516020525f5260405f20805460a0518082018281106159d0579050905081555060a05160166060516020525f5260405f20806040516020525f5260405f20905054101561596957602660c0527f4552433230207472616e7366657220696e73756666696369656e7420616c6c6f60e0527f77616e63652e00000000000000000000000000000000000000000000000000006101005260c05060c0518060e001601f825f031636823750506308c379a0608052602060a052601f19601f60c0510116604401609cfd5b60166060516020525f5260405f20806040516020525f5260405f209050805460a0518082038281116159d057905090508155506080516060517fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60a05160c052602060c0a3565b5f80fd00015b260400155aae0501515c4e07249b5ad60a00605ba60803f65a66090c475b460c00735be60800065c260548545a060c80d0e2750a58000506fdde030068000594bf804d0fce0045b68a6a670aa60005f40b817d036e0025bc157ac116220065095ea7b3192b00454a44f4cb0b92000523b872dd18e600656e553f6516150045a39a45b7023a0025bccabb7513a50005bc5c98b70678018538d52e0f01020005228bfd9f01650025b3d7f6b90f990025c8a872cb0aec000595d89b4100ae000518160ddd01c50005125151d701b900058da5cb5b0110000570a0823101d1002524fe17210b3c002505935a4f01a10005313ce56700f40005e134a7f704c90025e2c02ee5177b00c5a64fa59909ef0065b613ab9708150025f1e42ccd195c0045ef8b30f70f3c0025ce96cb77113c002521ab18870ca700250a28a477118d0025c55b0091015900055aa6e675011b000560a916d00127000501e1d1140a6a0005a2de9ae80dc200653f4ee62c08cf00c5b87b8a10163500a5e37074560cba00654ef501ac013300257d92535c089c0085870774120da20005736d8b6c146100a571f06c280a080085c1665ba00b9f00258d5a59380ab00025a10801600af60025320ad2ba0852004507a2d13a0edf00251d2ac68c01ad0005a318c1a417680085733272a0122800a5ba087652121d0065b460af94175b0065414e8486014d0005c6e6f5920eaa002596fee0600bb2006500c435030a7a0005af62a18f068301c5ae24a3a9019500055959397509e30045402d267d0f140025a9059cbb18b100458675c757142900453e1dcc7f141c002591dc418a143e00654cdad50611e80025a706bc840daf0025dd62ed3e01f70045c63d75b60f710025d905777e11c200252a068b460b32000525c4d9e8083e00251f55182a086f0065f94a7dfe0fd900858484ac7406230005d9c99c940c9a000500000000000000000000000000000000000000000000000000000004a817c80000000000000000000000000000000000000000000000000000000000000000144164617074657220536176696e677320445941440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000573445941440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000fd03723a9a3abe0562451496a9a394d2c4bad4ab
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.