Yearn Token Vault. Holds an underlying token, and allows users to interact
with the Yearn ecosystem through Strategies connected to the Vault.
Vaults are not limited to a single Strategy, they can have as many Strategies
as can be designed (however the withdrawal queue is capped at 20.)
Deposited funds are moved into the most impactful strategy that has not
already reached its limit for assets under management, regardless of which
Strategy a user's funds end up in, they receive their portion of yields
generated across all Strategies.
When a user withdraws, if there are no funds sitting undeployed in the
Vault, the Vault withdraws funds from Strategies in the order of least
impact. (Funds are taken from the Strategy that will disturb everyone's
gains the least, then the next least, etc.) In order to achieve this, the
withdrawal queue's order must be properly set and managed by the community
Vault Strategies are parameterized to pursue the highest risk-adjusted yield.
There is an "Emergency Shutdown" mode. When the Vault is put into emergency
shutdown, assets will be recalled from the Strategies as quickly as is
practical (given on-chain conditions), minimizing loss. Deposits are
halted, new Strategies may not be added, and each Strategy exits with the
minimum possible damage to position, while opening up deposits to be
withdrawn by users. There are no restrictions on withdrawals above what is
expected under Normal Operation.
For further details, please refer to the specification:
API_VERSION: constant(String) = "0.3.0"
from vyper.interfaces import ERC20
def name() -> String: view
def symbol() -> String: view
def decimals() -> uint256: view
def want() -> address: view
def vault() -> address: view
def estimatedTotalAssets() -> uint256: view
def withdraw(_amount: uint256) -> uint256: nonpayable
def migrate(_newStrategy: address): nonpayable
def authorized(guest: address, amount: uint256) -> bool: view
# NOTE: Track the total for overhead targeting purposes
strategies: public(HashMap[address, StrategyParams])
MAXIMUM_STRATEGIES: constant(uint256) = 20
# Ordering that `withdraw` uses to determine which strategies to pull funds from
# NOTE: Does *NOT* have to match the ordering of all the current strategies that
# exist, but it is recommended that it does or else withdrawal depth is
# limited to only those inside the queue.
# NOTE: Ordering is determined by governance, and should be balanced according
# to risk, slippage, and/or volatility. Can also be ordered to increase the
# withdrawal speed of a particular Strategy.
# NOTE: The first time a ZERO_ADDRESS is encountered, it stops withdrawing
depositLimit: public(uint256) # Limit for totalAssets the Vault can hold
debtRatio: public(uint256) # Debt ratio for the Vault across all strategies (in BPS, <= 10k)
totalDebt: public(uint256) # Amount of tokens that all strategies have borrowed
lastReport: public(uint256) # block.timestamp of last report
activation: public(uint256) # block.timestamp of contract deployment
rewards: public(address) # Rewards contract where Governance fees are sent to
# Governance Fee for management of Vault (given to `rewards`)
# Governance Fee for performance of Vault (given to `rewards`)
MAX_BPS: constant(uint256) = 10_000 # 100%, or 10k basis points
SECS_PER_YEAR: constant(uint256) = 31_557_600 # 365.25 days
# `nonces` track `permit` approvals with signature.
nonces: public(HashMap[address, uint256])
DOMAIN_TYPE_HASH: constant(bytes32) = keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')
PERMIT_TYPE_HASH: constant(bytes32) = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")
guardian: address = msg.sender,
Initializes the Vault, this is called only once, when the contract is
The performance fee is set to 10% of yield, per Strategy.
The management fee is set to 2%, per year.
The initial deposit limit is set to 0 (deposits disabled); it must be
updated after initialization.
If `nameOverride` is not specified, the name will be 'yearn'
combined with the name of `token`.
If `symbolOverride` is not specified, the symbol will be 'y'
combined with the symbol of `token`.
@param token The token that may be deposited into this Vault.
@param governance The address authorized for governance interactions.
@param rewards The address to distribute rewards to.
@param nameOverride Specify a custom Vault name. Leave empty for default choice.
@param symbolOverride Specify a custom Vault symbol name. Leave empty for default choice.
@param guardian The address authorized for guardian interactions. Defaults to caller.
assert self.activation == 0 # dev: no devops199
self.token = ERC20(token)
self.name = concat(DetailedERC20(token).symbol(), " yVault")
self.symbol = concat("yv", DetailedERC20(token).symbol())
self.symbol = symbolOverride
self.decimals = DetailedERC20(token).decimals()
self.governance = governance
self.management = governance
self.performanceFee = 1000 # 10% of yield (per Strategy)
log UpdatePerformanceFee(convert(1000, uint256))
self.managementFee = 200 # 2% per year
log UpdateManagementFee(convert(200, uint256))
self.lastReport = block.timestamp
self.activation = block.timestamp