Dolomite Margin - Glossary
To understand how Dolomite Margin works, it's essential to understand the following glossary of terms, which makes up its architecture.
DolomiteMargin is Account based. Each Account is referenced by its owner wallet address and an account number unique to that owner address. Accounts have balances on each asset supported by DolomiteMargin, which can be either positive (indicating a net supply of the asset) or negative (indicating a net borrow of an asset). Accounts must maintain a certain level of collateralization, or they will be liquidated.
Wallet address
0x6b5Bb4E60821eCE7363CaFf836Be1A4f9e3559B3
has the following balances in its account number 123456
:- ETH: 1,000
- DAI: -10,000
- USDC: -5,000
This account is borrowing 10,000 DAI and 5,000 USDC. These borrows are collateralized by 1,000 ETH. The account will earn interest on ETH and pay interest on DAI and USDC.
Interest rates in DolomiteMargin are dynamic and set per Market. Each interest rate is automatically and algorithmically set based on the ratio of
(total borrow) / (total supply)
of that Market. Account balances either continuously earn (if positive) or pay (if negative) interest.Interest is earned / paid continuously (down to the second). Rates on the protocol are denominated yearly in APR.
There are two types of balances amounts on DolomiteMargin: Wei and Par.
Wei refers to the actual token amount of an asset held in or owed by an account. Wei amounts are constantly changing as interest accrues on the balance. For example, if Bob deposits 10 DAI to a DolomiteMargin Account, its Wei balance would initially be 10. The balance would start increasing every second as Bob started earning interest on his DAI.
Likely, most times you will want to use Wei balances.
Par refers to an interest adjusted amount that is static and does not change on the protocol. These are the balances that are actually stored on the protocol smart contracts. The protocol uses the current market index (see below) to transform Par to Wei values.
Each Market has a global borrow index and supply index. These indexes are used to transform Par <-> Wei values using the formula:
Borrow Wei Balance = (Borrow Par Balance) * (Borrow Market Index)
and
Supply Wei Balance = (Supply Par Balance) * (Supply Market Index)
Indexes start at 1 upon the addition of the Market to the protocol. They increase based on how much interest has accrued for that asset. For example upon adding USDC both the borrow index and supply index for USDC were 1. Say over the next month 2% interest accrues to borrowers and 1% interest accrues to lenders (based on the interest rates and time that has passed). After this, the supply index will be 1.01, and the borrow index will be 1.02. These indexes will keep increasing based on interest accrued, forever.
Alice deposits 10 DAI to the protocol (10 DAI in Wei). The supply index on DAI is currently 2. Using
Supply Par Balance = (Supply Wei Balance) / (Supply Market Index) = 10 / 2 = 5
, the protocol credits 5 Par balance to Alice's account.Later, interest has accrued for DAI on the protocol, and now the supply index for DAI is 3. Now, Alice goes to withdraw her DAI. Her DAI Par balance is still 5 (Par does not change over time). Now the protocol calculates
Supply Wei Balance = (Supply Par Balance) * (Supply Market Index) = 5 * 3 = 15
, and sends Alice 15 DAI.All state changes to an account happen through Actions. Actions can modify the balances of 1 or more Accounts. There is no such thing as a "Borrow" action on DolomiteMargin. Rather, actions can automatically borrow funds if Account balances decrease a user's balance below 0. The following Actions are supported by DolomiteMargin:
Deposit funds into an Account. Funds are moved from the sender or an approved address to DolomiteMargin, and the Account's balance is incremented.
Withdraw funds from an Account. Funds are sent from DolomiteMargin to a specified address and the Account's balance is decremented.
Transfer funds internally between two DolomiteMargin accounts. This action can only be invoked by an approved operator for both accounts.
Buy an asset on a decentralized exchange using another asset. Uses an Exchange Wrapper to interact with different decentralized exchanges. Causes the bought asset's balance to go up, and the asset used to do the buy's balance to go down. Example: Buy 1 WETH on Uniswap using DAI
There are no fees charged by Dolomite for performing this action. Performing a
Buy
action that reduces the user's balance to less than 0 (therefore making the Buy
a flashloan) do not incur any Dolomite-specific fees. Users are still responsible for paying the fees charged by the external decentralized exchange they are using.Sell an asset on a decentralized exchange for another asset. Uses an Exchange Wrapper to interact with different decentralized exchanges. Causes the sold asset's balance to go down, and the received assets balance to go up. Example: Sell 1 WETH on Uniswap for DAI
There are no fees charged by Dolomite for performing this action. Performing a
Sell
action that reduces the user's balance to less than 0 (therefore making the Sell
a flashloan) do not incur any Dolomite-specific fees. Users are still responsible for paying the fees charged by the external decentralized exchange they are using.Trade assets with another account on DolomiteMargin internally. No actual tokens are moved, but Account balances are updated. Uses the
AutoTrader
interface, which allows a smart contract to be specified which is called to determine the price of the trade.The fees charged by Dolomite for performing this action depend on the implementation of the specific
IAutoTrader
contract. For example, the simple x * y = k
AMM pools used by Dolomite charge a 0.3% fee for trades, which is factored into the trade price. If the instance of IAutoTrader is set to special
on Dolomite Margin, then the instance of IAutoTrader can only be interacted with via a Global Operator.Liquidates an undercollateralized Account. Operates on two Accounts: the liquidating Account, and the undercollateralized Account. Does not transfer any tokens, but just internally updates balances of accounts. This action can only be invoked on
DolomiteMargin
through a Global Operator
. Liquidates at the price specified by the oracle. Example:Starting Account Balances:
Liquidating Account (L): +100 DAI
Undercollateralized Account (U): -1 ETH, +140 DAI
ETH oracle price: $125
DAI oracle price: $1
Liquidation spread: 5%
The liquidate action causes 1 ETH to be transferred from L -> U, and
1 ETH * (($125/ETH) / ($1/DAI)) * 1.05 = 131.25 DAI
to be transferred from U -> L. After the liquidation the balances will be:Liquidating Account (L): +231.25 DAI, -1 ETH
Undercollateralized Account (U): +8.75 DAI
Pulls extra funds from the insurance fund to re-collateralize an underwater account with only negative balances.
Every state changing action to the protocol occurs through an Operation. Operations contain a series of Actions that each operate on an Account.
Multiple Actions can be strung together in an Operation to achieve more complex interactions with the protocol. For example, taking a short ETH position on DolomiteMargin could be achieved with an Operation containing the following Actions:
Sell ETH for DAI
Deposit DAI
Importantly collateralization is only checked at the end of an operation, so accounts are allowed to be transiently undercollateralized in the scope of one Operation. This allows for Operations like a Sell -> Trade, where an asset is first sold, and the collateral is locked up as the second Action in the Operation.
Operators are entities that perform actions on behalf of an account. They come in three forms:
- 1.The calling address (
msg.sender
) which interacts withDolomiteMargin
- 2.A local operator, which is set when an Account calls
setOperators(...)
. This is similar to setting a token approval, where an Account specifies which contracts (operators) can interact on their behalf. - 3.A global operator, which is set by the owner of
DolomiteMargin
to automatically allow a contract to interact on behalf of any account onDolomiteMargin
. Global operators generally exist for two reasons:- 1.To provide liquidation smart contracts for underwater accounts
- 2.To offer a smoother UX, since less set up needs to be taken per-user to enable certain features on the platform.
Amounts in DolomiteMargin are denominated by 3 things:
value
- the numerical value of the Amountreference
- one of:AmountReference.Delta
Indicates an amount relative to the existing balanceAmountReference.Target
Indicates an absolute amount
denomination
- one of:AmountDenomination.Wei
Indicates the amount is denominated in the actual units of the token being transferred ( See Wei)AmountDenomination.Par
Indicates the amount is denominated in "principal". DolomiteMargin uses these types of amounts in its internal accounting, and they do not change over time (See Par)
A very important thing to note is that amounts are always relative to how the balance of the Account being Operated on will change, not the amount of the Action occurring. So, for example you'd say
withdraw(-10)
, because when you Withdraw, the balance of the Account will decrease.