AlchemistV2

The AlchemistV2 is the core contract in any Alchemix debt-system that holds Account data and issues that system's debt tokens. The AlchemistV2 is 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).

Functions

Interface

Accounts

An Account in the Alchemist has multiple components. The first 2 data-points to understand are balances and ** debt**.

Balances is a mapping of 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 AlchemistV2 avoid bank-run scenarios.

Debt is an int256 type that represents both the account's debt (positive values) and credit (negative values).

A Account manages its debt by tracking the lastAccruedWeights of the various depositedTokens that it is holding.

A Account also has the ability to track mintAllowances and withdrawAllowances that allow 3rd-party accounts to mint and withdraw its assets.

Risk Management

Whitelisting

As a security precaution, certain action methods in the Alchemist are whitelisted, meaning that, when msg.sender is 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.

Maximum Expected Value

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.

Maximum Loss

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 withdrawUnderlying or liquidate functions. When _checkLoss is 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 maximumLoss bps, 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:

  • deposit()

  • depositUnderlying()

  • withdrawUnderlying()

  • withdrawUnderlyingFrom()

  • liquidate()

  • harvest()

Importantly, the following functions are still useable:

  • withdraw()

  • withdrawFrom()

  • repay()

  • mint()

  • burn()

The maximumLoss is 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 maximumLoss around 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.

Mint, Repay, and Liquidate Caps

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, repay() liquidate(), and mint() all have time-based limits to how much they can be used.

Each underlying token registered in an Alchemist has its own repay and liquidate limit that keeps track of the total amount of funds repaid or liquidated globally. Each synthetic token has its own mint limit 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.

Sentinels

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:

  • deposit()

  • depositUnderlying()

  • liquidate()

  • repay()

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.

Last updated