AlchemistV2is the core contract in any Alchemix debt-system that holds Account data and issues that system's debt tokens. The
AlchemistV2is flexible enough to accept deposits in the form of either yield-bearing-assets or underlying collateral assets (and wrapping said underlying tokens into their yield-bearing form).
Alchemisthas multiple components. The first 2 data-points to understand are balances and ** debt**.
Balances is a
mappingof yieldTokens to the
Account's respective balance of Alchemist-shares. ** Shares** represent a user's deposit of yieldTokens in the
AlchemistV2, and provide an accounting abstraction that helps the
AlchemistV2avoid bank-run scenarios.
Debt is an
int256type that represents both the account's debt (positive values) and credit (negative values).
Accountmanages its debt by tracking the lastAccruedWeights of the various depositedTokens that it is holding.
Accountalso has the ability to track mintAllowances and withdrawAllowances that allow 3rd-party accounts to mint and withdraw its assets.
As a security precaution, certain action methods in the Alchemist are whitelisted, meaning that, when
msg.senderis another contract, that contract must be whitelisted by governance in order for the call to succeed.
There is no such whitelist restriction for EOA's. Any EOA can ALWAYS interact with the AlchemistV2 without needing to be whitelisted.
As the system matures, this whitelist can be disabled by governance.
Each yield token accepted by the Alchemist has a configured maximum expected value. For each yield token, the total value (denominated in underlying tokens) of the balance of that yield token held by the Alchemist may not exceed its maximum expected value.
Maximum expected value functions as a tunable deposit limit, allowing governance to limit the acceptable exposure that a synthetic asset has to each individual vault that collateralizes it.
AlchemistV2 was built to gracefully handle vault losses. The Alchemix debt systems will operate nominally when a loss of 1-25 bps (actual value set by governance) occurs. Losses larger than this trigger the “check loss” circuit breaker, which exists to prevent users from realizing too much slippage when calling the
_checkLossis called, it calculates the current-value of *yX*, or “how much of underlying token *uX* is currently represented by the amount of the yield token *yX* that the Alchemist holds”. The current-value of *yX* is compared to the expected-value of *yX* (a number calculated every time *yX* is deposited, withdrawn, or liquidated from the Alchemist). If the current-value is less than expected-value by more than the governance-configured
maximumLossbps, the transaction will fail.
Each yield token accepted by the Alchemist has a configured maximum amount of loss that it can experience and still function normally. If the vault loses more than the specified
maximumLoss(denominated in basis-points), the following functions are automatically disabled:
Importantly, the following functions are still useable:
maximumLossis configured as an amount of basis-points of the total expected value of the vault. Because there are situations where a vault might experience a small, transient loss, it will likely be wise to keep
maximumLossaround 1-25 bps.
In the event a vault experiences a loss that is sufficient to disable functionality and is deemed by the DAO to be non-transient, the
snap()function can be called to reset the expected value of the yield tokens held by the Alchemist, thereby accepting the loss and resuming normal operation.
Due to the arbitrage inherent to the Alchemix V2 system, it is important to have stop-gap measures in place to prevent massive capital movements that could harm the backing of synthetic assets. To address this,
mint()all have time-based limits to how much they can be used.
Each underlying token registered in an Alchemist has its own
liquidatelimit that keeps track of the total amount of funds repaid or liquidated globally. Each synthetic token has its own
mintlimit that keeps track of the total amount of funds minted globally. These limits each track their given metric and linearly cool down over a specified amount of time.
For example, if governance sets the
liquidate()cap for DAI to 20 million with a 10 minute cooldown, then the maximum amount of DAI that can be liquidated from all of the strategies used by the alUSD Alchemist over the span of 10 minutes is 20 million. The cooldown period is linear, so if the 20 million cap gets hit, no more DAI can be liquidated in that block, but after 5 minutes users can liquidate up to 10 million DAI.
The sentinels of V2 serve a function similar to the one they did in V1: allow trusted external accounts to disable access to deposit funds into a vault that has been compromised. If a yield token or underlying token is disabled, the following functions are not useable:
Importantly, users can still withdraw their funds. The
harvest()function also still functions so debts can continue to be repaid by yield.
The long-term goal is for sentinels to be decentralized keeper bots that monitor chain state and pause underlying and yield tokens based on certain safety triggers.