<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Vault Protocol on</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/</link><description>Recent content in Vault Protocol on</description><generator>Hugo -- 0.152.2</generator><language>en-us</language><atom:link href="https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/index.xml" rel="self" type="application/rss+xml"/><item><title>Vaults</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/1-vaults/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/1-vaults/</guid><description>&lt;p&gt;Fluid has 4 types of vaults:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;T1 vaults -&amp;gt; 1 collateral token / 1 debt token&lt;/li&gt;
&lt;li&gt;T2 vaults -&amp;gt; 2 collateral tokens (smart collateral) / 1 debt token&lt;/li&gt;
&lt;li&gt;T3 vaults -&amp;gt; 1 collateral token / 2 debt tokens (smart debt)&lt;/li&gt;
&lt;li&gt;T4 vaults -&amp;gt; 2 collateral tokens (smart collateral) / 2 debt tokens (smart debt)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are going to analyze only T1 vaults for this module, as that&amp;rsquo;s enough to understand the core idea behind managing positions and the liquidation engine.&lt;/p&gt;</description></item><item><title>1st supply/withdraw no debt</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/2-first-supply-withdraw-no-debt/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/2-first-supply-withdraw-no-debt/</guid><description>&lt;p&gt;To keep things simpler at the start, let&amp;rsquo;s just completely ignore the borrow side at the moment, and only analyze how user interaction with the vault protocol works on plain supply and withdraw.&lt;/p&gt;
&lt;p&gt;In the code below, we will hide all code that triggers on borrow behind &lt;code&gt;...&lt;/code&gt; and only focus on supply/withdrawal operations.&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/vault/operate-supply-withdraw.png"
alt="Vault protocol" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;We can divide this flow into 11 steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sanity checks&lt;/li&gt;
&lt;li&gt;Setup of memory vars&lt;/li&gt;
&lt;li&gt;Creation of new position&lt;/li&gt;
&lt;li&gt;Update of exchange prices&lt;/li&gt;
&lt;li&gt;Calculation of supply or withdrawal amounts&lt;/li&gt;
&lt;li&gt;Assign of new tick&lt;/li&gt;
&lt;li&gt;Calculation of health factor&lt;/li&gt;
&lt;li&gt;Update of user position in storage&lt;/li&gt;
&lt;li&gt;Withdrawal gap check&lt;/li&gt;
&lt;li&gt;Execution of operation&lt;/li&gt;
&lt;li&gt;Update of vault variables in storage&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="1-sanity-checks"&gt;1. Sanity checks&lt;/h2&gt;
&lt;p&gt;We first check for reentrancy.&lt;/p&gt;</description></item><item><title>2nd supply/withdraw no debt</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/3-second-supply-withdraw-no-debt/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/3-second-supply-withdraw-no-debt/</guid><description>&lt;p&gt;Everything stays the same, the only difference is that now we are working with existing NFT, meaning we are not passing &lt;code&gt;0&lt;/code&gt; to main &lt;code&gt;operate&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;If we look at the implementation, we see that we only unlock this new code below in second if case during position fetching:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/vault/nft-exists.png"
alt="Vault protocol" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;Code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Checks nft ownership if we are doing withdraw or borrow as those operations affect health factor&lt;/li&gt;
&lt;li&gt;Checks if there exists valid non empty position for passed NFT. This ensures that NFT is from this vault we are interacting with&lt;/li&gt;
&lt;li&gt;Fetch and convert supply amount and store it in temp struct for memory variables&lt;/li&gt;
&lt;li&gt;Fetch and convert debt amount and store it in temp struct for memory variables&lt;/li&gt;
&lt;li&gt;Assign new tick. Note because this is supply only position, tick get&amp;rsquo;s default value of &lt;code&gt;type(int).min&lt;/code&gt; just like on first supply&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Ticks</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/4-ticks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/4-ticks/</guid><description>&lt;p&gt;On the previous pages, we were ignoring ticks as we weren&amp;rsquo;t dealing with debt, but what are the ticks?&lt;/p&gt;
&lt;p&gt;If you are familiar with ticks from Uniswap V3, then the same thing ticks are for concentrated liquidity there, here they are for separating positions by their ratio.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ratio = 1.0015^tick
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where ratio is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ratio = debt / coll
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;higher the ratio -&amp;gt; higher the tick -&amp;gt; higher the risk of liquidation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and vice versa&lt;/p&gt;</description></item><item><title>Ticks data structures</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/5-ticks-data-structures/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/5-ticks-data-structures/</guid><description>&lt;p&gt;Before we dive into borrow flow, let&amp;rsquo;s quickly introduce some tick data structures that will help us later to understand the code better.&lt;/p&gt;
&lt;p&gt;Note that we will analyze liquidations in depth later, so some of these concepts will only make sense then, but I want to introduce them now so we conceptually know what is going on.&lt;/p&gt;
&lt;h2 id="tickdata"&gt;TickData&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-solidity" data-lang="solidity"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// mapping tickId =&amp;gt; tickData
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// Tick related data. Total debt &amp;amp; other things
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// First bit =&amp;gt; 0 =&amp;gt; If 1 then liquidated else not liquidated
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// Next 24 bits =&amp;gt; 1-24 =&amp;gt; Total IDs. ID should start from 1.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// If not liquidated:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// Next 64 bits =&amp;gt; 25-88 =&amp;gt; raw debt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// If liquidated
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// The below 3 things are of last ID. This is to be updated when user creates a new position
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// Next 1 bit =&amp;gt; 25 =&amp;gt; Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated (100% liquidated)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// Next 30 bits =&amp;gt; 26-55 =&amp;gt; branch ID where this tick got liquidated
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;/// Next 50 bits =&amp;gt; 56-105 =&amp;gt; debt factor 50 bits (35 bits coefficient | 15 bits expansion)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;mapping&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int256&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;uint256&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;internal&lt;/span&gt; tickData;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;TickData&lt;/code&gt; describes the latest info for some tick. We will call that info the latest epoch.&lt;/p&gt;</description></item><item><title>Borrow for the first time</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/6-borrow-first-time/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/6-borrow-first-time/</guid><description>&lt;p&gt;We are doing borrow for the first time. We still only have a supply position, and our tick has the initial value of &lt;code&gt;type(int).min&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We are only going to scan relevant code that we deliberately skipped during the first supply scan of the main &lt;code&gt;operate&lt;/code&gt; function: &lt;a href="https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/2-first-supply-withdraw-no-debt/"&gt;Supply/Withdraw for the first&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="calculate-debt-raw"&gt;Calculate debt raw&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-solidity" data-lang="solidity"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(o_.liquidityExPrice, , o_.supplyExPrice, o_.borrowExPrice) &lt;span style="color:#f92672"&gt;=&lt;/span&gt; updateExchangePrices(o_.vaultVariables2);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// supply or withdraw
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// borrow or payback
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (newDebt_ &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// borrow new debt, rounding up adding extra wei in debt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; temp_ &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ((&lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt;(newDebt_) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; EXCHANGE_PRICES_PRECISION) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; o_.borrowExPrice) &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// if borrow fee is 0 then it&amp;#39;ll become temp_ + 0.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Only adding fee in o_.debtRaw and not in newDebt_ as newDebt_ is debt that needs to be borrowed from Liquidity
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// as we have added fee in debtRaw hence it will get added in user&amp;#39;s position &amp;amp; vault&amp;#39;s total borrow.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; &lt;span style="color:#75715e"&gt;// It can be collected with rebalance function.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; o_.debtRaw &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; temp_ &lt;span style="color:#f92672"&gt;+&lt;/span&gt; (temp_ &lt;span style="color:#f92672"&gt;*&lt;/span&gt; ((o_.vaultVariables2 &lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;82&lt;/span&gt;) &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; X10)) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// final user&amp;#39;s debt should not be above 2**128 bits
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (o_.debtRaw &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; X128) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; revert FluidVaultError(ErrorTypes.Vault__UserCollateralDebtExceed);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We calculated exchange prices and want to calculate the debt raw amount.&lt;/p&gt;</description></item></channel></rss>