Example #1
0
    def describe(self):
        scale = 10**self.decimals
        info = {
            "vault balance": self.vault.balance() / scale,
            "share price": self.vault.getPricePerFullShare() / 1e18,
            "vault total": self.vault.totalSupply() / scale,
            "strategy balance": self.strategy.balanceOf() / scale,
        }

        # some of the oldest vaults don't implement these methods
        if hasattr(self.vault, "available"):
            info["available"] = self.vault.available() / scale

        if hasattr(self.vault, "min") and hasattr(self.vault, "max"):
            info["strategy buffer"] = self.vault.min() / self.vault.max()

        # new curve voter proxy vaults
        if hasattr(self.strategy, "proxy"):
            vote_proxy = interface.CurveYCRVVoter(self.strategy.voter())
            # curve swap is broken across several strategies
            swap = interface.CurveSwap(
                constants.CURVE_SWAP_OVERRIDES.get(self.strategy._name,
                                                   self.strategy.curve()))
            gauge = interface.CurveGauge(self.strategy.gauge())
            info.update(curve.calculate_boost(gauge, vote_proxy))
            info.update(curve.calculate_apy(gauge, swap))
            info["earned"] = gauge.claimable_tokens.call(vote_proxy).to(
                "ether")

        if hasattr(self.strategy, "earned"):
            info["lifetime earned"] = self.strategy.earned() / scale

        if self.strategy._name == "StrategyYFIGovernance":
            ygov = interface.YearnGovernance(self.strategy.gov())
            info["earned"] = ygov.earned(self.strategy) / 1e18
            info["reward rate"] = ygov.rewardRate() / 1e18
            info["ygov balance"] = ygov.balanceOf(self.strategy) / 1e18
            info["ygov total"] = ygov.totalSupply() / 1e18

        if "token price" not in info:
            if self.name in ["aLINK"]:
                info["token price"] = uniswap.token_price(
                    self.vault.underlying())
            elif self.name in ["USDC", "TUSD", "DAI", "USDT"]:
                info["token price"] = 1
            else:
                info["token price"] = uniswap.token_price(self.token)

        info["tvl"] = info["vault balance"] * info["token price"]
        return info
Example #2
0
    def describe(self):
        scale = 10**self.vault.decimals()
        strats = [str(strat.strategy) for strat in self.strategies]
        strats.extend([ZERO_ADDRESS] * (40 - len(strats)))
        try:
            info = {
                "totalAssets": self.vault.totalAssets() / scale,
                "maxAvailableShares": self.vault.maxAvailableShares() / scale,
                "pricePerShare": self.vault.pricePerShare() / scale,
                "debtOutstanding": self.vault.debtOutstanding() / scale,
                "creditAvailable": self.vault.creditAvailable() / scale,
                "expectedReturn": self.vault.expectedReturn() / scale,
                "totalSupply": self.vault.totalSupply() / scale,
                "emergencyShutdown": self.vault.emergencyShutdown(),
                "depositLimit": self.vault.depositLimit() / scale,
                "debtRatio": self.vault.debtRatio(),
                "totalDebt": self.vault.totalDebt() / scale,
                "lastReport": self.vault.lastReport(),
                "managementFee": self.vault.managementFee(),
                "performanceFee": self.vault.performanceFee(),
                "strategies": {},
            }
        except ValueError as e:
            info = {"strategies": {}}
        for strat in self.strategies:
            info["strategies"][strat.name] = strat.describe()

        info["token price"] = uniswap.token_price(self.vault.token())
        if "totalAssets" in info:
            info["tvl"] = info["token price"] * info["totalAssets"]

        return info
Example #3
0
def describe_ironbank(markets):
    blocks_per_year = 365 * 86400 / 15
    contracts = [m.ctoken for m in markets]
    results = multicall_matrix(
        contracts,
        [
            "exchangeRateCurrent",
            "getCash",
            "totalBorrows",
            "totalSupply",
            "totalReserves",
            "supplyRatePerBlock",
            "borrowRatePerBlock",
        ],
    )
    output = defaultdict(dict)
    for m in markets:
        res = results[m.ctoken]
        price = uniswap.token_price(m.underlying)
        exchange_rate = res["exchangeRateCurrent"] * 10 ** (m.cdecimals - m.decimals - 18)
        for attr in ["getCash", "totalBorrows", "totalReserves"]:
            res[attr] /= 10 ** m.decimals

        tvl = (res["getCash"] + res["totalBorrows"] - res["totalReserves"]) * price
        supplied = res["getCash"] + res["totalBorrows"] - res["totalReserves"]
        ratio = res["totalBorrows"] / supplied if supplied != 0 else None

        output[m.name] = {
            "total supply": res["totalSupply"] / 10 ** m.cdecimals,
            "total cash": res["getCash"],
            "total supplied": supplied,
            "total borrows": res["totalBorrows"],
            "total reserves": res["totalReserves"],
            "exchange rate": exchange_rate,
            "token price": price * exchange_rate,
            "underlying price": price,
            "supply apy": res["supplyRatePerBlock"] / 1e18 * blocks_per_year,
            "borrow apy": res["borrowRatePerBlock"] / 1e18 * blocks_per_year,
            "utilization": ratio,
            "tvl": tvl,
        }

    return dict(output)
Example #4
0
def describe_iearn(iearn: List[iEarn]) -> dict:
    contracts = [x.contract for x in iearn]
    results = multicall_matrix(
        contracts, ["totalSupply", "pool", "getPricePerFullShare", "balance"])
    output = defaultdict(dict)

    for i in iearn:
        res = results[i.contract]
        price = token_price(i.token)
        output[i.name] = {
            "total supply": res["totalSupply"] / 10**i.decimals,
            "available balance": res["balance"] / 10**i.decimals,
            "pooled balance": res["pool"] / 10**i.decimals,
            "price per share": res["getPricePerFullShare"] / 1e18,
            "token price": price,
            "tvl": res["pool"] / 10**i.decimals * price,
        }

    return dict(output)
Example #5
0
def get_base_price(pool_or_lp):
    # try to find pool for lp, otherwise assume pool
    pool = lp_to_pool(pool_or_lp)
    if pool == ZERO_ADDRESS:
        pool = pool_or_lp
    return uniswap.token_price(get_underlying(pool)[0])
Example #6
0
    def describe(self):
        scale = 10**self.decimals
        info = {}
        try:
            info['share price'] = self.vault.getPricePerFullShare() / 1e18
        except ValueError:
            # no money in vault, exit early
            return {'tvl': 0}

        attrs = {
            'vault balance': [self.vault, 'balance'],
            'vault total': [self.vault, 'totalSupply'],
            'strategy balance': [self.strategy, 'balanceOf'],
        }

        # some of the oldest vaults don't implement these methods
        if hasattr(self.vault, "available"):
            attrs['available'] = [self.vault, 'available']

        if hasattr(self.vault, "min") and hasattr(self.vault, "max"):
            attrs['min'] = [self.vault, 'min']
            attrs['max'] = [self.vault, 'max']

        # new curve voter proxy vaults
        if hasattr(self.strategy, "proxy"):
            results = fetch_multicall(
                [self.strategy, 'voter'],
                [curve.registry, 'get_pool_from_lp_token', self.token],
                [self.strategy, 'gauge'],
            )
            vote_proxy = interface.CurveYCRVVoter(results[0])
            swap = interface.CurveSwap(results[1])
            gauge = interface.CurveGauge(results[2])
            info.update(curve.calculate_boost(gauge, vote_proxy))
            info.update(curve.calculate_apy(gauge, swap))
            info["earned"] = gauge.claimable_tokens.call(vote_proxy).to(
                "ether")

        if hasattr(self.strategy, "earned"):
            info["lifetime earned"] = self.strategy.earned() / scale

        if self.strategy._name == "StrategyYFIGovernance":
            ygov = interface.YearnGovernance(self.strategy.gov())
            attrs["earned"] = [ygov, 'earned', self.strategy]
            attrs["reward rate"] = [ygov, 'rewardRate']
            attrs["ygov balance"] = [ygov, 'balanceOf', self.strategy]
            attrs["ygov total"] = [ygov, 'totalSupply']

        # fetch attrs as multicall
        try:
            results = fetch_multicall(*attrs.values())
        except ValueError:
            pass
        else:
            for name, attr in zip(attrs, results):
                info[name] = attr / scale

        # some additional post-processing
        if 'min' in info:
            info["strategy buffer"] = info.pop('min') / info.pop('max')

        if "token price" not in info:
            if self.name in ["aLINK"]:
                info["token price"] = uniswap.token_price(
                    self.vault.underlying())
            elif self.name in ["USDC", "TUSD", "DAI", "USDT"]:
                info["token price"] = 1
            else:
                info["token price"] = uniswap.token_price(self.token)

        info["tvl"] = info["vault balance"] * info["token price"]
        return info