예제 #1
0
    def __init__(self):
        self.registry = interface.YRegistry(web3.ens.resolve("registry.ychad.eth"))
        addresses_provider = contract("0x9be19Ee7Bc4099D62737a7255f5c227fBcd6dB93")
        addresses_generator_v1_vaults = contract(addresses_provider.addressById("ADDRESSES_GENERATOR_V1_VAULTS"))

        # NOTE: we assume no more v1 vaults are deployed
        self.vaults = [VaultV1(vault_address, *self.registry.getVaultInfo(vault_address)) for vault_address in addresses_generator_v1_vaults.assetsAddresses()]
예제 #2
0
    def apy(self, _: ApySamples) -> Apy:
        curve_3_pool = contract("0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7")
        curve_reward_distribution = contract(
            "0xA464e6DCda8AC41e03616F95f4BC98a13b8922Dc")
        curve_voting_escrow = contract(
            "0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2")
        voter = "0xF147b8125d2ef93FB6965Db97D6746952a133934"
        crv_price = magic.get_price(
            "0xD533a949740bb3306d119CC777fa900bA034cd52")
        yvecrv_price = magic.get_price(
            "0xc5bDdf9843308380375a611c18B50Fb9341f502A")

        total_vecrv = curve_voting_escrow.totalSupply()
        yearn_vecrv = curve_voting_escrow.balanceOf(voter)
        vault_supply = self.vault.totalSupply()

        week = 7 * 86400
        epoch = math.floor(time() / week) * week - week
        tokens_per_week = curve_reward_distribution.tokens_per_week(
            epoch) / 1e18
        virtual_price = curve_3_pool.get_virtual_price() / 1e18
        # although we call this APY, this is actually APR since there is no compounding
        apy = (tokens_per_week * virtual_price * 52) / (
            (total_vecrv / 1e18) * crv_price)
        vault_boost = (yearn_vecrv / vault_supply) * (crv_price / yvecrv_price)
        composite = {
            "currentBoost": vault_boost,
            "boostedApy": apy * vault_boost,
            "totalApy": apy * vault_boost,
            "poolApy": apy,
            "baseApy": apy,
        }
        return Apy("backscratcher", apy, apy, ApyFees(), composite=composite)
예제 #3
0
    def get_balances(self, pool, block=None):
        """
        Get {token: balance} of liquidity in the pool.
        """
        factory = self.get_factory(pool)
        coins = self.get_coins(pool)
        decimals = self.get_decimals(pool)

        try:
            if factory:
                source = contract(factory)
            elif self.crypto_swap_registry_supports_pool(pool):
                source = self.crypto_swap_registry
            else:
                source = self.registry

            balances = source.get_balances(pool, block_identifier=block)
        # fallback for historical queries
        except ValueError:
            balances = fetch_multicall(*[[contract(pool), 'balances', i]
                                         for i, _ in enumerate(coins)])

        if not any(balances):
            raise ValueError(f'could not fetch balances {pool} at {block}')

        return {
            coin: balance / 10**dec
            for coin, balance, dec in zip(coins, balances, decimals)
            if coin != ZERO_ADDRESS
        }
예제 #4
0
파일: v3.py 프로젝트: yearn/yearn-exporter
    def __init__(self):
        if chain.id not in addresses:
            raise UnsupportedNetwork(
                'compound is not supported on this network')

        conf = addresses[chain.id]
        self.factory = contract(conf['factory'])
        self.quoter = contract(conf['quoter'])
        self.fee_tiers = conf['fee_tiers']
예제 #5
0
 def load_registry(self):
     if chain.id == Network.Mainnet:
         return self.load_from_ens()
     elif chain.id == Network.Fantom:
         return [contract('0x727fe1759430df13655ddb0731dE0D0FDE929b04')]
     elif chain.id == Network.Arbitrum:
         return [contract('0xC8f17f8E15900b6D6079680b15Da3cE5263f62AA')]
     else:
         raise UnsupportedNetwork(
             'yearn v2 is not available on this network')
예제 #6
0
 def get_address(self, name):
     """
     Get contract from Synthetix registry.
     See also https://docs.synthetix.io/addresses/
     """
     address_resolver = contract(addresses[chain.id])
     address = address_resolver.getAddress(
         encode_single('bytes32', name.encode()))
     proxy = contract(address)
     return contract(proxy.target()) if hasattr(proxy, 'target') else proxy
예제 #7
0
def test_get_v1_strategy():
    old_block = 10532708
    vault = next(x for x in registry.vaults if x.vault == '0x597aD1e0c13Bfe8025993D9e79C69E1c0233522e')
    assert vault.get_controller(old_block) == contract('0x31317F9A5E4cC1d231bdf07755C994015A96A37c')

    assert vault.get_strategy(old_block) is None
    assert vault.get_strategy(old_block + 100) == contract('0x003312E3eBBe6b0f25f1c03C2695d83075d9a9B8')
    assert vault.get_strategy(old_block + 1000) == contract('0xea061fDd1cd80176455bDb314C87d78570a8fb26')

    new_block = 10640746
    assert vault.get_controller(new_block) == vault.controller
예제 #8
0
 def __contains__(self, token):
     """
     Check if a token is a synth.
     """
     token = contract(token)
     if not hasattr(token, 'target'):
         return False
     target = token.target()
     if target in self.synths and contract(target).proxy() == token:
         return True
     return False
예제 #9
0
 def unit_debt(self, block=None) -> dict:
     if block and block < 11315910:
         return
     # ychad = contract('ychad.eth')
     ychad = contract('0xfeb4acf3df3cdea7399794d0869ef76a6efaff52')
     unitVault = contract("0xb1cff81b9305166ff1efc49a129ad2afcd7bcf19")
     yfi = "0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e"
     usdp = '0x1456688345527bE1f37E9e627DA0837D6f08C925'
     debt = unitVault.getTotalDebt(yfi, ychad,
                                   block_identifier=block) / 10**18
     debt = {usdp: {'balance': debt, 'usd value': debt}}
     return debt
예제 #10
0
    def get_gauge(self, pool):
        """
        Get liquidity gauge address by pool.
        """
        factory = self.get_factory(pool)
        if factory and hasattr(contract(factory), 'get_gauge'):
            gauge = contract(factory).get_gauge(pool)
            if gauge != ZERO_ADDRESS:
                return gauge

        gauges, types = self.registry.get_gauges(pool)
        if gauges[0] != ZERO_ADDRESS:
            return gauges[0]
예제 #11
0
def get_token_from_event(event):
    try:
        transfer = event['Transfer']
        address = transfer[0].address
        # try to download the contract from etherscan
        contract(address)
        return address
    except ValueError:
        # some tokens have unverified sources with etherscan, skip them!
        return None
    except EventLookupError:
        logger.critical(event)
        raise
예제 #12
0
    def get_decimals(self, pool):
        factory = self.get_factory(pool)
        source = contract(factory) if factory else self.registry
        decimals = source.get_decimals(pool)

        # pool not in registry
        if not any(decimals):
            coins = self.get_coins(pool)
            decimals = fetch_multicall(
                *[[contract(token), 'decimals'] for token in coins]
            )
        
        return [dec for dec in decimals if dec != 0]
예제 #13
0
 def __post_init__(self):
     self.vault = contract(self.vault)
     self.controller = contract(self.controller)
     self.strategy = contract(self.strategy)
     self.token = contract(self.token)
     if str(self.vault) not in constants.VAULT_ALIASES:
         logger.warning(
             "no vault alias for %s, reading from vault.sybmol()",
             self.vault)
     self.name = constants.VAULT_ALIASES.get(str(self.vault),
                                             self.vault.symbol())
     self.decimals = self.vault.decimals(
     )  # vaults inherit decimals from token
     self.scale = 10**self.decimals
예제 #14
0
    def __init__(self):
        if chain.id not in curve_contracts:
            raise UnsupportedNetwork("curve is not supported on this network")

        addrs = curve_contracts[chain.id]
        if chain.id == Network.Mainnet:
            self.crv = contract(addrs['crv'])
            self.voting_escrow = contract(addrs['voting_escrow'])
            self.gauge_controller = contract(addrs['gauge_controller'])

        self.pools = set()
        self.identifiers = defaultdict(list)
        self.addres_provider = contract(addrs['address_provider'])
        self.watch_events()
예제 #15
0
 def unit_collateral(self, block=None) -> dict:
     if block and block < 11315910:
         return
     # ychad = contract('ychad.eth')
     ychad = contract('0xfeb4acf3df3cdea7399794d0869ef76a6efaff52')
     unitVault = contract("0xb1cff81b9305166ff1efc49a129ad2afcd7bcf19")
     yfi = "0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e"
     bal = unitVault.collaterals(yfi, ychad, block_identifier=block)
     collateral = {
         yfi: {
             'balance': bal / 10**18,
             'usd value': bal / 10**18 * get_price(yfi, block),
         }
     }
     return collateral
예제 #16
0
def test_curve_lp_price_oracle_historical(name):
    if name in ['linkusd']:
        pytest.xfail('no active market')

    token = web3.toChecksumAddress(pooldata[name]['lp_token_address'])
    swap = web3.toChecksumAddress(pooldata[name]['swap_address'])
    deploy = contract_creation_block(swap)
    # sample 10 blocks over the pool lifetime
    blocks = [
        int(block) for block in np.linspace(deploy + 10000, chain.height, 10)
    ]
    prices = []
    for block in blocks:
        try:
            prices.append(curve.curve.get_price(token, block))
        except (PriceError, TypeError):
            prices.append(None)

    virtual_prices = [
        contract(swap).get_virtual_price(block_identifier=block) / 1e18
        for block in blocks
    ]

    print(
        tabulate(list(zip(blocks, prices, virtual_prices)),
                 headers=['block', 'price', 'vp']))
예제 #17
0
    def calculate_apy(self, gauge, lp_token, block=None):
        crv_price = magic.get_price(self.crv)
        pool = contract(self.get_pool(lp_token))
        results = fetch_multicall(
            [gauge, "working_supply"],
            [self.gauge_controller, "gauge_relative_weight", gauge],
            [gauge, "inflation_rate"],
            [pool, "get_virtual_price"],
            block=block,
        )
        results = [x / 1e18 for x in results]
        working_supply, relative_weight, inflation_rate, virtual_price = results
        token_price = magic.get_price(lp_token, block=block)
        try:
            rate = (inflation_rate * relative_weight * 86400 * 365 /
                    working_supply * 0.4) / token_price
        except ZeroDivisionError:
            rate = 0

        return {
            "crv price": crv_price,
            "relative weight": relative_weight,
            "inflation rate": inflation_rate,
            "virtual price": virtual_price,
            "crv reward rate": rate,
            "crv apy": rate * crv_price,
            "token price": token_price,
        }
예제 #18
0
def multi(address: str,
          pool_price: int,
          base_asset_price: int,
          block: Optional[int] = None) -> float:
    multi_rewards = contract(address)

    total_supply = multi_rewards.totalSupply(
        block_identifier=block) if hasattr(multi_rewards, "totalSupply") else 0

    queue = 0
    apr = 0
    if hasattr(multi_rewards, "rewardsToken"):
        token = multi_rewards.rewardTokens(queue, block_identifier=block)
    else:
        token = None
    while token and token != ZERO_ADDRESS:
        try:
            data = multi_rewards.rewardData(token, block_identifier=block)
        except ValueError:
            token = None
        if data.periodFinish >= time():
            rate = data.rewardRate / 1e18 if data else 0
            token_price = get_price(token, block=block) or 0
            apr += SECONDS_PER_YEAR * rate * token_price / (
                (pool_price / 1e18) * (total_supply / 1e18) * token_price)
        queue += 1
        try:
            token = multi_rewards.rewardTokens(queue, block_identifier=block)
        except ValueError:
            token = None
    return apr
예제 #19
0
def get_price(token, block=None):
    pool = contract(token)
    tokens, supply = fetch_multicall([pool, "getCurrentTokens"],
                                     [pool, "totalSupply"],
                                     block=block)
    supply = supply / 1e18
    balances = fetch_multicall(*[[pool, "getBalance", token]
                                 for token in tokens],
                               block=block)
    balances = [
        balance / 10**contract(token).decimals()
        for balance, token in zip(balances, tokens)
    ]
    total = sum(balance * magic.get_price(token, block=block)
                for balance, token in zip(balances, tokens))
    return total / supply
예제 #20
0
 def maker_debt(self, block=None) -> dict:
     proxy_registry = contract('0x4678f0a6958e4D2Bc4F1BAF7Bc52E8F3564f3fE4')
     cdp_manager = contract('0x5ef30b9986345249bc32d8928B7ee64DE9435E39')
     # ychad = contract('ychad.eth')
     ychad = contract('0xfeb4acf3df3cdea7399794d0869ef76a6efaff52')
     vat = contract('0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B')
     proxy = proxy_registry.proxies(ychad)
     cdp = cdp_manager.first(proxy)
     urn = cdp_manager.urns(cdp)
     ilk = encode_single('bytes32', b'YFI-A')
     art = vat.urns(ilk, urn, block_identifier=block).dict()["art"]
     rate = vat.ilks(ilk, block_identifier=block).dict()["rate"]
     debt = art * rate / 1e45
     dai = '0x6B175474E89094C44Da98b954EedeAC495271d0F'
     debt = {dai: {'balance': debt, 'usd value': debt}}
     return debt
예제 #21
0
파일: v3.py 프로젝트: yearn/yearn-exporter
    def get_price(self, token, block=None):
        if block and block < contract_creation_block(UNISWAP_V3_QUOTER):
            return None

        if token == usdc:
            return 1

        paths = []
        if token != weth:
            paths += [[token, fee, weth, self.fee_tiers[0], usdc]
                      for fee in self.fee_tiers]

        paths += [[token, fee, usdc] for fee in self.fee_tiers]

        scale = 10**contract(token).decimals()

        results = fetch_multicall(
            *[[self.quoter, 'quoteExactInput',
               self.encode_path(path), scale] for path in paths],
            block=block,
        )

        outputs = [
            amount / self.undo_fees(path) / 1e6
            for amount, path in zip(results, paths) if amount
        ]
        return max(outputs) if outputs else None
예제 #22
0
    def __init__(self):
        if chain.id not in registries:
            raise UnsupportedNetwork(
                'chainlink is not supported on this network')

        self.registry = contract(registries[chain.id])
        self.load_feeds()
예제 #23
0
 def balances(self, blocks):
     bentobox = contract('0xF5BCE5077908a1b7370B9ae04AdC565EBd643966')
     vault = Vault.from_address(self.vault)
     balances = batch_call(
         [[bentobox, 'balanceOf', self.vault, self.wrapper, block]
          for block in blocks])
     return [(balance or 0) / vault.scale for balance in balances]
예제 #24
0
 def from_address(cls, address):
     vault = contract(address)
     instance = cls(vault=vault,
                    token=vault.token(),
                    api_version=vault.apiVersion())
     instance.name = vault.name()
     return instance
예제 #25
0
    def __init__(self,
                 vault,
                 api_version=None,
                 token=None,
                 registry=None,
                 watch_events_forever=True):
        self._strategies = {}
        self._revoked = {}
        self._reports = []
        self.vault = vault
        self.api_version = api_version
        if token is None:
            token = vault.token()
        self.token = contract(token)
        self.registry = registry
        self.scale = 10**self.vault.decimals()
        # multicall-safe views with 0 inputs and numeric output.
        self._views = safe_views(self.vault.abi)

        # load strategies from events and watch for freshly attached strategies
        self._topics = [[
            encode_hex(event_abi_to_log_topic(event))
            for event in self.vault.abi
            if event["type"] == "event" and event["name"] in STRATEGY_EVENTS
        ]]
        self._watch_events_forever = watch_events_forever
        self._done = threading.Event()
        self._thread = threading.Thread(target=self.watch_events, daemon=True)
예제 #26
0
    def process_events(self, events):
        for event in events:
            logger.debug("%s %s %s", event.address, event.name, dict(event))
            if event.name == "NewGovernance":
                self.governance = event["governance"]

            if event.name == "NewRelease":
                self.releases[event["api_version"]] = contract(
                    event["template"])

            if event.name == "NewVault":
                # experiment was endorsed
                if event["vault"] in self._experiments:
                    vault = self._experiments.pop(event["vault"])
                    vault.name = f"{vault.vault.symbol()} {event['api_version']}"
                    self._vaults[event["vault"]] = vault
                    logger.debug("endorsed vault %s %s", vault.vault,
                                 vault.name)
                # we already know this vault from another registry
                elif event["vault"] not in self._vaults:
                    vault = self.vault_from_event(event)
                    vault.name = f"{vault.vault.symbol()} {event['api_version']}"
                    self._vaults[event["vault"]] = vault
                    logger.debug("new vault %s %s", vault.vault, vault.name)

            if event.name == "NewExperimentalVault":
                vault = self.vault_from_event(event)
                vault.name = f"{vault.vault.symbol()} {event['api_version']} {event['vault'][:8]}"
                self._experiments[event["vault"]] = vault
                logger.debug("new experiment %s %s", vault.vault, vault.name)

            if event.name == "VaultTagged":
                self.tags[event["vault"]] = event["tag"]
예제 #27
0
 def get_price(self, token, block=None):
     if block is None or block >= self.registry_deploy_block:
         return self.registry.price(token, block_identifier=block) / 1e18
     else:
         # fallback method for before registry deployment
         oracle = contract(self.registry.oracle())
         ctoken = self.registry.cy(token)
         return oracle.getUnderlyingPrice(ctoken, block_identifier=block) / 1e18
예제 #28
0
    def __init__(self):
        if chain.id not in addresses:
            raise UnsupportedNetwork("fixed forex is not supported on this network")

        self.registry = contract(addresses[chain.id])
        self.registry_deploy_block = contract_creation_block(addresses[chain.id])
        self.markets = self.registry.forex()
        logger.info(f'loaded {len(self.markets)} fixed forex markets')
예제 #29
0
def get_assets_metadata(vault_v2: list) -> dict:
    registry_v2_adapter = contract(web3.ens.resolve("lens.ychad.eth"))
    addresses = [str(vault.vault) for vault in vault_v2]
    assets_dynamic_data = registry_v2_adapter.assetsDynamic(addresses)
    assets_metadata = {}
    for datum in assets_dynamic_data:
        assets_metadata[datum[0]] = datum[-1]
    return assets_metadata
예제 #30
0
    def get_strategy(self, block=None):
        if self.name in ["aLINK", "LINK"] or block is None:
            return self.strategy

        controller = self.get_controller(block)
        strategy = controller.strategies(self.token, block_identifier=block)
        if strategy != ZERO_ADDRESS:
            return contract(strategy)