Overview
The Vaults contract is the core of the protocol, the contract that takes care of the minting and burning of all FxDAO stablecoins. In this page, we will take a look at some fey keys to understand how the contract works.
The contract interface:
pub trait VaultsContractTrait {
fn init(
e: Env,
admin: Address,
protocol_manager: Address,
col_token: Address,
stable_issuer: Address,
treasury: Address,
fee: u128,
oracle: Address,
);
fn get_core_state(e: Env) -> CoreState;
fn set_address(e: Env, typ: u32, address: Address);
fn upgrade(e: Env, hash: BytesN<32>);
fn set_panic(e: Env, status: bool);
fn set_next_key(e: Env, target_key: VaultKey, next_key: OptionalVaultKey);
fn create_currency(e: Env, denomination: Symbol, contract: Address);
fn get_currency(e: Env, denomination: Symbol) -> Currency;
fn toggle_currency(e: Env, denomination: Symbol, active: bool);
fn set_vault_conditions(
e: Env,
min_col_rate: u128,
min_debt_creation: u128,
opening_col_rate: u128,
denomination: Symbol,
);
fn get_vaults_info(e: Env, denomination: Symbol) -> VaultsInfo;
fn calculate_deposit_ratio(currency_rate: u128, collateral: u128, debt: u128) -> u128;
fn new_vault(
e: Env,
prev_key: OptionalVaultKey,
caller: Address,
initial_debt: u128,
collateral_amount: u128,
denomination: Symbol,
);
fn get_vault(e: Env, caller: Address, denomination: Symbol) -> Vault;
fn get_vault_from_key(e: Env, vault_key: VaultKey) -> Vault;
fn get_vaults(
e: Env,
prev_key: OptionalVaultKey,
denomination: Symbol,
total: u32,
only_to_liquidate: bool,
) -> Vec<Vault>;
fn increase_collateral(
e: Env,
prev_key: OptionalVaultKey,
vault_key: VaultKey,
new_prev_key: OptionalVaultKey,
amount: u128,
);
fn increase_debt(
e: Env,
prev_key: OptionalVaultKey,
vault_key: VaultKey,
new_prev_key: OptionalVaultKey,
amount: u128,
);
fn pay_debt(
e: Env,
prev_key: OptionalVaultKey,
vault_key: VaultKey,
new_prev_key: OptionalVaultKey,
amount: u128,
);
fn redeem(e: Env, caller: Address, denomination: Symbol);
fn liquidate(
e: Env,
liquidator: Address,
denomination: Symbol,
total_vaults_to_liquidate: u32,
) -> Vec<Vault>;
}
A linked list of Vaults
The protocol logic requires that at all times we know what is the riskiest Vault, and for that, we sort all the Vaults from the riskiest to the safest one. Because of blockchain limitations, we can not just simply loop/query the whole storage and find the Vaults that meet this criteria, so we use a linked list of Vaults that are connected and it's easy for the contract to find/add/update/remove entries from this list.
Each Vault has a unique VaultKey
which can be generated with data from Vault and it follows this structure:
pub struct VaultKey {
pub index: u128,
pub account: Address,
pub denomination: Symbol,
}
This Key will let the contract know where it can find the target Vault and so this is the value used to "connect" each Vault in the linked list.
The key has three values: index
, account
, and denomination
. Let's see what they are:
The Vault's Index
The Vault index is the value that tells the "position" of the contract in terms of the risk, this index is generated using the amount of the collateral and the amount of the debt issued. Because the parameter is not related to the real-world "value" of both the collateral and debt, it gives the risk of the Vault in terms of the amounts being used.
The value is calculated like this:
pub fn calculate_user_vault_index(total_debt: u128, total_collateral: u128) -> u128 {
(1_000000000 * total_collateral) / (total_debt)
}
We use 7 digits because all the assets used in the protocol are Stellar Classic Assets
Account
This is the Address
of the owner of the Vault, being a simple Address
means the owner can be either a regular Stellar account or a Soroban contract.
Denomination
The denomination is the Symbol of the code of the synthetic currency issued by FxDAO. For example, the asset USDx represents the value of the USD Dollar, which means that the Symbol is USD
(All currency denominations are uppercase).