Skip to main content

Creating a Vault

In FxDAO, synthetic coins (stablecoins) are issued in the form of debt, this debt is backed by collateral (XLM), and the position is denominated as a "Vault". A Vault represents the debt and collateral a user has with the protocol and it's created based on the denomination of the currency.

The process of minting and burning the stablecoins is automatic when a user locks or withdraws the collateral from the protocol. If there is no debt, a new Vault is created, if all debt is paid then the Vault is deleted.

Because FxDAO relies on a linked list, it's important to know the position of a new/existing Vault before interacting with it. In the following examples, we will explain how to create a new Vault and how to calculate the position of this Vault.

Creating a new Vault in the protocol

Before creating our vault, we need to calculate the position of our new Vault. In order to do that we will follow the next steps:

  • Calculate the new Vault index and generate the Vault Key
  • Check if there are Vaults already created in the protocol with the same denomination
  • If there are Vaults already, we look for the lowest and nearest index to our new Vault.

For this example, let's assume we want to create a Vault with a debt of 100 USDx and a collateral of 1100 XLM.

Calculating the index and creating the VaultKey

First, we need to calculate the index, by using the method from here we calculate that our index is: 1100_0000000. With this value calculated, we can create the VaultKey as:

In this example we are not taking into consideration the fee the network might charge from the collateral, you should subtract that amount from the collateral before calculating the index

let new_vault_key: VaultKey = VaultKey {
index: 1100_0000000u128,
account: ACCOUNT_ADDRESS,
denomination: symbol_short!("USD"),
};

Checking the lowest Vault created for our denomination

Once we have our VaultKey we need to know where in the linked list should be placed, for that the first step is knowing if there are already Vaults in the protocol (with the same denomination) and knowing that we will get the lowest_key which is saved/updated at all time in the storage key VaultsInfo(Symbol). To do that we can call the contract method get_vaults_info with the denomination we want:

let lowest_key: OptionalVaultKey = contract_client.get_vaults_info(&symbol_short!("USD")).lowest_key;

OptionalVaultKey is basically a simulation of the logic Optional follows in Rust. At the moment of creating this protocol, it wasn't possible to save Optional values in the storage.

If the value is OptionalVaultKey::None means there is no Vault created for this denomination, while if the value is OptionalVaultKey::Some(v) then there are Vaults created for this denomination.

Let's assume the lowest_key value from the VaultsInfo is OptionalVaultKey::None which means there are no Vaults for this denomination. Let's call the contract and create the first Vault by calling the method new_vault:

contract_client.new_vault(
&OptionalVaultKey::None,
&ACCOUNT_ADDRESS,
&100_0000000u128,
&1100_0000000u128,
&symbol_short!("USD")
);

After this call, your Vault should have been created. The reason we used OptionalVaultKey::None as the prev_key is that there is no Vault that should be in the linked list before the one we are creating.

Looking for the right position to place our new Vault when there are Vaults already created

When the lowest_key is not OptionalVaultKey::None, it means that there are more Vaults in the linked list so we should check where we should place our new Vault. We can have two cases:

The lowest_key index is higher than our Vault's index

When this happens, you should use OptionalVaultKey::None as prev_key when calling the new_vault method. It basically works as if there is no Vault created.

The lowest_key index is lower than our Vault's index

If this is the case, then you should get the next keys so until you find a Vault which has a lower index than you but its next key is higher than yours.

For example, let's imagine this is the current linked list for the USD currency:

In this case, your new Vault should be introduced next to the one with index 1000_0000000. Let's call the contract method:

contract_client.new_vault(
&OptionalVaultKey::Some(VaultKey {
index: 1000_0000000u128,
account: OWNER_OF_THIS_VAULT,
denomination: symbol_short!("USD")
}),
&ACCOUNT_ADDRESS,
&100_0000000u128,
&1100_0000000u128,
&symbol_short!("USD")
);

After you do this call, the linked list will be updated and it will look like this:

Minimum debt, collateral ratio, and opening ratio

The protocol has three variable values that are important when creating a new Vault, these values are included in the VaultsInfo value for each denomination (USDx vaults could have different values from EURx vaults).

  • min_col_rate: The minimum collateral rate a Vault can have before being open for liquidation, for example, if 110% is the moment a Vault can be liquidated then this value will be: 1_1000000u128.
  • opening_col_rate: The minimum collateral rate a Vault can have at the moment of being created, for example, if 115% is the minimum then this value will be: 1_1500000u128.
  • min_debt_creation: The minimum debt that can be issued for a Vault.