<?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>Liquidity Layer on</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/</link><description>Recent content in Liquidity Layer 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/3-liquidity-layer/index.xml" rel="self" type="application/rss+xml"/><item><title>Operate: Sanity checks</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/1-sanity-checks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/1-sanity-checks/</guid><description>&lt;p&gt;The operate function starts from performing few sanity checks. We are looking at this code:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/liquidity-layer/1-sanity-checks.png"
alt="Liquidity layer" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;Remember that this function handles all operations in one place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;supplyAmount &amp;gt; 0&lt;/code&gt; -&amp;gt; we are doing a regular supply&lt;/li&gt;
&lt;li&gt;&lt;code&gt;supplyAmount &amp;lt; 0&lt;/code&gt; -&amp;gt; we are withdrawing liquidity&lt;/li&gt;
&lt;li&gt;&lt;code&gt;borrowAmount &amp;gt; 0&lt;/code&gt; -&amp;gt; we are doing a regular borrow&lt;/li&gt;
&lt;li&gt;&lt;code&gt;borrowAmount &amp;lt; 0&lt;/code&gt; -&amp;gt; we are paying back borrowed assets&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So we perform straightforward sanity checks in this order:&lt;/p&gt;</description></item><item><title>Operate: Setup memory variables</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/2-setup-memory-variables/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/2-setup-memory-variables/</guid><description>&lt;p&gt;After we performed sanity checks, we want to set up memory variables which will help us later to perform various calculations during the function.&lt;/p&gt;
&lt;p&gt;We are looking at this piece of code:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/liquidity-layer/2-setup-memory-vars.png"
alt="Liquidity layer" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;First, we initialize &lt;code&gt;OperateMemoryVars&lt;/code&gt;. This is just a common pattern to group local variables inside one struct to prevent stack too deep errors.&lt;/p&gt;
&lt;p&gt;Then we are introduced to variables &lt;code&gt;memVar_&lt;/code&gt; and &lt;code&gt;memVar2_&lt;/code&gt;. This is a pattern heavily used across the Fluid codebase, where &lt;code&gt;memVar_&lt;/code&gt;, &lt;code&gt;memVar1_&lt;/code&gt; &amp;hellip; &lt;code&gt;memVarN_&lt;/code&gt; are temporary variables that are reused across calculations and assignments to avoid creating new ones, with the goal of reducing gas cost.&lt;/p&gt;</description></item><item><title>Operate: Dex callback</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/3-dex-callback/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/3-dex-callback/</guid><description>&lt;p&gt;After setup of memory variables, we are looking at this piece of code, which we are going to skip and won&amp;rsquo;t analyze.&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/liquidity-layer/3-dex-callback.png"
alt="Liquidity layer" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;Because we are &amp;ldquo;only&amp;rdquo; analyzing T1 vaults in this guide, and this piece of code is only used for DEX vaults (T2, T3, T4).&lt;/p&gt;
&lt;p&gt;To prove that to you, we are going to cheat a little bit and jump to the place in the code where T1 vaults (consumers of this liquidity) use this &lt;code&gt;operate&lt;/code&gt; function. Note that T1 vaults will be analyzed later in this guide in separate &lt;code&gt;Vault Protocol&lt;/code&gt; section.&lt;/p&gt;</description></item><item><title>Operate: Eth payment check</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/4-eth-payment-check/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/4-eth-payment-check/</guid><description>&lt;p&gt;After the skipped DEX callback, we are looking at this piece of code:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/liquidity-layer/4-eth-payment-check.png"
alt="Liquidity layer" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;If you remember, &lt;code&gt;memVar2_&lt;/code&gt; was calculated as &lt;code&gt;deposit + payback&lt;/code&gt; amount, so its purpose was for this check, where we want to make sure the caller has sent enough native token:&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-solidity" data-lang="solidity"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;memVar2_ &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; msg.value
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But also not too much above the excess allowance limit:&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-solidity" data-lang="solidity"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;msg.value &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; (memVar2_ &lt;span style="color:#f92672"&gt;*&lt;/span&gt; (FOUR_DECIMALS &lt;span style="color:#f92672"&gt;+&lt;/span&gt; memVar3_)) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; FOUR_DECIMALS
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where:&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-solidity" data-lang="solidity"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;memVar3_ &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;100&lt;/span&gt;; &lt;span style="color:#75715e"&gt;// MAX_INPUT_AMOUNT_EXCESS = 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;&lt;/span&gt;FOUR_DECIMALS &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;e4;
&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;// 10100 / 10000 = 1.01
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So this simply reverts if we sent 1% more native token than the combined deposit plus payback amount passed in the function call, to prevent the caller from accidentally passing more tokens than needed.&lt;/p&gt;</description></item><item><title>Operate: Send funds from sender</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/5-send-funds-from-sender/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/5-send-funds-from-sender/</guid><description>&lt;p&gt;After the ETH payment check, we want to send funds from the caller to this liquidity layer.&lt;/p&gt;
&lt;p&gt;This is the snippet of code we are looking at:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/liquidity-layer/5-send-funds-from-sender.png"
alt="Liquidity layer" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;At first, we see that we want to transfer tokens only if &lt;code&gt;memVar2_&lt;/code&gt; is greater than zero, meaning &lt;code&gt;deposit + payback != 0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For ETH transfers, this is already handled in the previous section by setting it to zero, which is also noted by the comment, so no new transfer is needed.&lt;/p&gt;</description></item><item><title>Operate: Update exchange prices / utilization / ratios</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/9-update-exchange-prices/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/9-update-exchange-prices/</guid><description>&lt;p&gt;Before we analyze, let&amp;rsquo;s quickly revisit some of the things we covered earlier &lt;a href="https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/6-calculate-exchange-prices/liquiditycalcs-calc-exchange-prices/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We previously brought exchange prices forward from the previous checkpoint to the current timestamp. During this action, we introduced the concept of &lt;code&gt;supplyRatio&lt;/code&gt; and &lt;code&gt;borrowRatio&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember that &lt;code&gt;supplyRatio&lt;/code&gt; and &lt;code&gt;borrowRatio&lt;/code&gt; always stay below 100% and represent the ratio between interest and interest-free supplying or borrowing.&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;if supplyInterestFree &amp;gt; supplyWithInterest
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; supplyRatio = supplyWithInterest / supplyInterestFree
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;else
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; supplyRatio = supplyInterestFree / supplyWithInterest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or&lt;/p&gt;</description></item><item><title>Operate: Send funds to sender</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/10-send-funds-to-sender/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/10-send-funds-to-sender/</guid><description>&lt;p&gt;We are almost finished with this main &lt;code&gt;operate&lt;/code&gt; function. As we finished all calculations, now we are only left to send funds to the user if he is using withdraw or borrow operation.&lt;/p&gt;
&lt;p&gt;This is the code we are analyzing.&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/liquidity-layer/send-funds-to-sender.png"
alt="Liquidity layer" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;First, this whole branch of using &lt;code&gt;o_.netTransfersOut&lt;/code&gt; can be skipped, as it is only used for DEXes, leaving us only the second branch to analyze.&lt;/p&gt;
&lt;p&gt;The code is straightforward. We first store borrow and withdraw amounts to memory variables:&lt;/p&gt;</description></item><item><title>Operate: Emit event and return</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/11-emit-event-and-return/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/11-emit-event-and-return/</guid><description>&lt;p&gt;Congratulations! We are done with the main &lt;code&gt;operate&lt;/code&gt; function. The only last thing we want to do is emit an event and return values for supply and borrow exchange price:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/liquidity-layer/log-operate.png"
alt="Liquidity layer" width="100%"/&gt;
&lt;/figure&gt;</description></item><item><title>Summary</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/12-summary/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/3-liquidity-layer/12-summary/</guid><description>&lt;p&gt;To summarize, we understood how the main &lt;code&gt;operate&lt;/code&gt; function from the liquidity layer works under the hood.&lt;/p&gt;
&lt;p&gt;We learned that Fluid keeps liquidity in one contract, and although we gave examples with test users like Bob and Alice, we know that users of this liquidity are actually other protocols that use it through one interface and the &lt;code&gt;operate&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;We also saw how interest can be divided into with-interest and interest-free groups, and how withdrawal and borrow limits can dictate how protocols use liquidity from this layer.&lt;/p&gt;</description></item></channel></rss>