<?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>Liquidate function on</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/8-liquidation/</link><description>Recent content in Liquidate function 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/8-liquidation/index.xml" rel="self" type="application/rss+xml"/><item><title>Liquidate: Sanity check and setup</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/8-liquidation/1-sanity-checks-and-setup/</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/8-liquidation/1-sanity-checks-and-setup/</guid><description>&lt;p&gt;We are entering the &lt;code&gt;liquidate&lt;/code&gt; function with the code below:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/vault/liquidate-sanity-checks.png"
alt="Vault protocol" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;Liquidator is sending:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;debtAmt_&lt;/code&gt; -&amp;gt; amount of debt to liquidate&lt;/li&gt;
&lt;li&gt;&lt;code&gt;colPerUnitDebt_&lt;/code&gt; -&amp;gt; min amount of collateral per one unit of debt that liquidator is expecting to get in return&lt;/li&gt;
&lt;li&gt;&lt;code&gt;to_&lt;/code&gt; -&amp;gt; where to send collateral tokens&lt;/li&gt;
&lt;li&gt;&lt;code&gt;absorb_&lt;/code&gt; -&amp;gt; whether liquidation should first consume absorbed debt (or better known as bad debt)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Upon entering the function, we first perform the standard reentrancy check:&lt;/p&gt;</description></item><item><title>Liquidate: Calculate liquidation and max ratio</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/8-liquidation/2-calculate-liquidation-and-max-ratio/</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/8-liquidation/2-calculate-liquidation-and-max-ratio/</guid><description>&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/vault/liquidate-calc-ratios.png"
alt="Vault protocol" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;This part of code calculates 2 things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;liquidation tick&lt;/li&gt;
&lt;li&gt;max tick&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The part for liquidation tick calculation is something we already covered when we were checking user health position &lt;a href="https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/6-borrow-first-time/#check-collateral-factor-health"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The only thing left to answer is what is max tick?&lt;/p&gt;
&lt;p&gt;Max tick is the upper limit where positions above it get 100% liquidated immediately. This limit is primarily used as the last line of defense against bad debt and has a separate flow.&lt;/p&gt;</description></item><item><title>Liquidate: Setup for liquidation loop</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/8-liquidation/4-setup-for-liquidation-loop/</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/8-liquidation/4-setup-for-liquidation-loop/</guid><description>&lt;p&gt;We are looking at this code:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/vault/liq-setup.png"
alt="Vault protocol" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;This code is just setup code with no new logic, so we will quickly run over it.&lt;/p&gt;
&lt;p&gt;We first validate that the input amount for debt to liquidate is not too low or too high:&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;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (debtAmt_ &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10000&lt;/span&gt; &lt;span style="color:#f92672"&gt;||&lt;/span&gt; debtAmt_ &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__InvalidLiquidationAmt);
&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;Then we set up memory variables that will be used later:&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;&lt;span style="color:#75715e"&gt;// setting up status if top tick is liquidated or not
&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;currentData_.tickStatus &lt;span style="color:#f92672"&gt;=&lt;/span&gt; vaultVariables_ &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; &lt;span style="color:#f92672"&gt;?&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; &lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&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 info is mainly used as a place holder to store temporary tick related data
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// (it can be current or ref using same memory variable)
&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;TickData &lt;span style="color:#66d9ef"&gt;memory&lt;/span&gt; tickInfo_;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;tickInfo_.tick &lt;span style="color:#f92672"&gt;=&lt;/span&gt; currentData_.tick;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After this, we load the current branch data to memory:&lt;/p&gt;</description></item><item><title>Liquidate: Liquidation loop</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/8-liquidation/5-liquidation-loop/</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/8-liquidation/5-liquidation-loop/</guid><description>&lt;p&gt;Finally, we are arriving at the core liquidation loop that will be the heart of this vault &lt;code&gt;liquidate&lt;/code&gt; function.&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/vault/main-liquidation-loop.png"
alt="Vault protocol" width="100%"/&gt;
&lt;/figure&gt;
&lt;p&gt;As seen on the image above, we can divide this function into different logical parts which we will analyze separately:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setup of local vars&lt;/li&gt;
&lt;li&gt;Calculation of current tick ratio&lt;/li&gt;
&lt;li&gt;Addition of new debt and collateral for liquidation&lt;/li&gt;
&lt;li&gt;Update of &lt;code&gt;tickHasDebt&lt;/code&gt; and next active tick search&lt;/li&gt;
&lt;li&gt;Finding the reference tick&lt;/li&gt;
&lt;li&gt;Finding the reference ratio&lt;/li&gt;
&lt;li&gt;Calculation of debt and collateral to liquidate&lt;/li&gt;
&lt;li&gt;Finish of liquidation loop&lt;/li&gt;
&lt;li&gt;Updating amounts and factors for next iteration&lt;/li&gt;
&lt;li&gt;Merging branches&lt;/li&gt;
&lt;li&gt;Updating tick and ratio for next iteration&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="setup-of-local-vars"&gt;Setup of local vars&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:#66d9ef"&gt;uint&lt;/span&gt; debtLiquidated_;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt; colLiquidated_;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;uint&lt;/span&gt; debtFactor_ &lt;span style="color:#f92672"&gt;=&lt;/span&gt; BigMathVault.TWO_POWER_64;
&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;TickHasDebt &lt;span style="color:#66d9ef"&gt;memory&lt;/span&gt; tickHasDebt_;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;unchecked&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; tickHasDebt_.mapId &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (currentData_.tick &lt;span style="color:#f92672"&gt;&amp;lt;&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:#f92672"&gt;?&lt;/span&gt; (((currentData_.tick &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;256&lt;/span&gt;) &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:#f92672"&gt;:&lt;/span&gt; (currentData_.tick &lt;span style="color:#f92672"&gt;/&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;256&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 start slowly by setting a few local variables that will be used later. Then we find the &lt;code&gt;mapId&lt;/code&gt; of the &lt;code&gt;tickHasDebt&lt;/code&gt; mapping for current &lt;code&gt;topTick&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Liquidate: Calculate net token amounts</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/8-liquidation/6-calculate-net-token-amounts/</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/8-liquidation/6-calculate-net-token-amounts/</guid><description>&lt;p&gt;We are mostly done with this function. We finished the liquidation loop, and now we need to calculate the exact amounts that need to be transferred to the liquidator.&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/vault/calc-exact-amount.png"
alt="Vault protocol" width="80%"/&gt;
&lt;/figure&gt;
&lt;p&gt;First, we convert amounts to net amounts by multiplying with exchange prices:&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;actualDebtAmt_ &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (currentData_.totalDebtLiq &lt;span style="color:#f92672"&gt;*&lt;/span&gt; memoryVars_.borrowExPrice) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; EXCHANGE_PRICES_PRECISION;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;actualColAmt_ &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (currentData_.totalColLiq &lt;span style="color:#f92672"&gt;*&lt;/span&gt; memoryVars_.supplyExPrice) &lt;span style="color:#f92672"&gt;/&lt;/span&gt; EXCHANGE_PRICES_PRECISION;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The reason for doing this is that we previously converted from net to raw before we started the liquidation loop, as ratio calculation works with raw amounts:&lt;/p&gt;</description></item><item><title>Liquidate: Token transfers</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/8-liquidation/7-token-transfers/</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/8-liquidation/7-token-transfers/</guid><description>&lt;p&gt;Once we have net token amounts, let&amp;rsquo;s perform liquidity transfers:&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/vault/liq-liquidity-transfers.png"
alt="Vault protocol" width="80%"/&gt;
&lt;/figure&gt;
&lt;p&gt;We first check if debt token is native token, in which case we refund back to liquidator any tokens not spent on liquidation:&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;SafeTransfer.safeTransferNative(msg.sender, msg.value &lt;span style="color:#f92672"&gt;-&lt;/span&gt; actualDebtAmt_);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After that, we perform the payback to liquidity layer, where debt tokens will be pulled from liquidator:&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;&lt;span style="color:#75715e"&gt;// payback at 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;LIQUIDITY.operate{ value&lt;span style="color:#f92672"&gt;:&lt;/span&gt; temp_ }(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; BORROW_TOKEN,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&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:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;(actualDebtAmt_),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;address&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:#66d9ef"&gt;address&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; abi.encode(msg.sender)
&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;And finally, we withdraw collateral tokens back to liquidator, again using liquidity layer:&lt;/p&gt;</description></item><item><title>Liquidate: Vault variables storage update</title><link>https://rajkoz.com/posts/fluid-vault-smart-contracts-deep-dive/4-vault-protocol/8-liquidation/8-vault-variables-storage-update/</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/8-liquidation/8-vault-variables-storage-update/</guid><description>&lt;p&gt;Finally, all that&amp;rsquo;s left to do for this &lt;code&gt;liquidate&lt;/code&gt; function is to update total vault supply and debt by lowering the liquidated amounts.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;vaultVariables&lt;/code&gt; will already contain updated branch data info after liquidation.&lt;/p&gt;
&lt;figure&gt;
&lt;img loading="lazy" src="https://rajkoz.com/fluid-vault/vault/liq-final-update.png"
alt="Vault protocol" width="80%"/&gt;
&lt;/figure&gt;
&lt;p&gt;After we perform the update, we emit the &lt;code&gt;LogLiquidate&lt;/code&gt; event with liquidated amounts:&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;emit LogLiquidate(msg.sender, actualColAmt_, actualDebtAmt_, to_);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description></item></channel></rss>