<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MY ZT</title>
    <description>The latest articles on DEV Community by MY ZT (@zt_myo).</description>
    <link>https://dev.to/zt_myo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2852479%2Fe52fd93a-4d72-4d0f-a0bb-b0a9278d5f52.jpg</url>
      <title>DEV Community: MY ZT</title>
      <link>https://dev.to/zt_myo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zt_myo"/>
    <language>en</language>
    <item>
      <title>✨ Curve V2 notes</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Fri, 18 Apr 2025 11:24:34 +0000</pubDate>
      <link>https://dev.to/zt_myo/curve-v2-notes-4p14</link>
      <guid>https://dev.to/zt_myo/curve-v2-notes-4p14</guid>
      <description>&lt;h1&gt;
  
  
  Math
&lt;/h1&gt;

&lt;p&gt;k0 controls how flat the curve is, and gamma controls the concentration of the liquidity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgrn5idoinzz9e8uurg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgrn5idoinzz9e8uurg7.png" alt="Image description" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4r6n5b7gizw642p4rab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4r6n5b7gizw642p4rab.png" alt="Image description" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  price scale
&lt;/h2&gt;

&lt;p&gt;The way curve V2 concentrates liquidity for price other than equal to 1 is by what curve V2 calls price scale. &lt;/p&gt;

&lt;p&gt;the price scale determines where liquidity is concentrated (D/2).&lt;/p&gt;

&lt;p&gt;transformed balances = actual balances * price scale.&lt;/p&gt;

&lt;p&gt;D/2 represents the transtorm balances of each token when the pool is perfectly balanced.&lt;/p&gt;

&lt;p&gt;with transformed balances, we can swap near D/2, where the action is like constant sum.&lt;/p&gt;

&lt;h2&gt;
  
  
  pool value
&lt;/h2&gt;

&lt;p&gt;how curve B2 compares different curve V2 AMMs that might have different price scale and that might also have different values for D?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzp5p0hzw9y1h31k4zhmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzp5p0hzw9y1h31k4zhmd.png" alt="Image description" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;us the constant product amm to construct the pool value in curve V2, this equation represents the value L in a constant product AMM:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dtbgpzcygpyc24wdpwb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dtbgpzcygpyc24wdpwb.png" alt="Image description" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Curve V2 repeg loss
&lt;/h2&gt;

&lt;p&gt;curve V2 makes a loss when it repegs to a different price scale.&lt;/p&gt;

&lt;p&gt;in practice, Curve V2 will not repegs to the spot price. It will make a decision to repeg the price scale or to keep it the same (This decision depends on whether Curve V2 has collected enough profit from swap fees so that it can cover the loss from repeg). &lt;/p&gt;

&lt;p&gt;So realistically , if it was to repeg to another price scale, it will be a new price scale that is in between the current price scale and the price scale at this spot price. Then the Curve V2 will &lt;strong&gt;recalculate&lt;/strong&gt; the D(reduce).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsxf7u9glpxijt1iir33.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsxf7u9glpxijt1iir33.png" alt="Image description" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfek7v5l7wh4lnqf82g4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfek7v5l7wh4lnqf82g4.png" alt="Image description" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, the only way that we can reach this point is by increasing the liquidity, and the only way to increase the liquidity is either to collect  swap fees or to have liquidity providers deposit more tokens.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>✨The Graph notes</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Sat, 12 Apr 2025 04:34:42 +0000</pubDate>
      <link>https://dev.to/zt_myo/the-graph-notes-3hcc</link>
      <guid>https://dev.to/zt_myo/the-graph-notes-3hcc</guid>
      <description>&lt;h2&gt;
  
  
  The Graph Concepts
&lt;/h2&gt;

&lt;p&gt;what data can Subgraphs query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;historical events&lt;/li&gt;
&lt;li&gt;state variable&lt;/li&gt;
&lt;li&gt;view/pure function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The data update mechanism of Subgraphs:&lt;/p&gt;

&lt;p&gt;Event-based updates (eventHandlers)&lt;br&gt;
Block-triggered update (blockHandlers)&lt;/p&gt;

&lt;h2&gt;
  
  
  GraphQL Basic Concepts
&lt;/h2&gt;

&lt;h2&gt;
  
  
  How to access blockchain data using subgraph?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Query directly on the playground.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xed2pluhl9o9de2td81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xed2pluhl9o9de2td81.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Querying through curl.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Querying through typescript.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to create a subgraph for a contract?
&lt;/h2&gt;

</description>
      <category>graphql</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>developers</category>
    </item>
    <item>
      <title>🚀 From Zero to a Web3 Developer 🔥 Solana development</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Sat, 22 Mar 2025 03:21:05 +0000</pubDate>
      <link>https://dev.to/zt_myo/solana-development-5155</link>
      <guid>https://dev.to/zt_myo/solana-development-5155</guid>
      <description>&lt;p&gt;clash: Allow LAN&lt;/p&gt;

&lt;p&gt;Windows Defender: Check all Clash related apps&lt;/p&gt;

&lt;p&gt;create a file: C:\Users&amp;lt;UserName&amp;gt;.wslconfig&lt;/p&gt;

&lt;p&gt;cmd run: wsl --shutdown&lt;/p&gt;

&lt;p&gt;edit .bashrc&lt;/p&gt;

&lt;p&gt;&lt;a href="https://eastmonster.github.io/2022/10/05/clash-config-in-wsl/" rel="noopener noreferrer"&gt;clash-config-in-wsl&lt;/a&gt;&lt;/p&gt;

</description>
      <category>development</category>
      <category>linux</category>
      <category>tooling</category>
      <category>networking</category>
    </item>
    <item>
      <title>✨ Uniswap V3 notes</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Mon, 17 Mar 2025 09:42:09 +0000</pubDate>
      <link>https://dev.to/zt_myo/uniswap-v3-notes-53gi</link>
      <guid>https://dev.to/zt_myo/uniswap-v3-notes-53gi</guid>
      <description>&lt;ul&gt;
&lt;li&gt;🌟 &lt;strong&gt;Intro&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;  ⚡️ Difference between V2 and V3
&lt;/li&gt;
&lt;li&gt;  ⚡️ Concentrated Liquidity
&lt;/li&gt;
&lt;li&gt;  ⚡️ Liquidity Price Graph
&lt;/li&gt;
&lt;li&gt;  ⚡️ V3 Contracts
&lt;/li&gt;
&lt;/ol&gt;




&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;Spot Price&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;  ⚡️ Price and Tick
&lt;/li&gt;
&lt;/ol&gt;




&lt;ul&gt;
&lt;li&gt;📐 &lt;strong&gt;Math&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;  ⚡️ Curve Equation
&lt;/li&gt;
&lt;li&gt;  ⚡️ Price Delta
&lt;/li&gt;
&lt;li&gt;  ⚡️ Liquidity Delta
&lt;/li&gt;
&lt;/ol&gt;




&lt;ul&gt;
&lt;li&gt;🎚️ &lt;strong&gt;Tick&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;  ⚡️ Tick Bitmap
&lt;/li&gt;
&lt;li&gt;  ⚡️ Flip a Tick
&lt;/li&gt;
&lt;li&gt;  ⚡️ Get Next Tick
&lt;/li&gt;
&lt;/ol&gt;




&lt;ul&gt;
&lt;li&gt;💰 &lt;strong&gt;Fee Algorithm&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;  ⚡️ Fee Equation
&lt;/li&gt;
&lt;li&gt;  ⚡️ Fee Growth
&lt;/li&gt;
&lt;li&gt;  ⚡️ Fee Growth Outside
&lt;/li&gt;
&lt;li&gt;  ⚡️ Position Fee
&lt;/li&gt;
&lt;li&gt;  ⚡️ Fee Code Summary
&lt;/li&gt;
&lt;/ol&gt;




&lt;ul&gt;
&lt;li&gt;🔄 &lt;strong&gt;Swap&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;  ⚡️ Liquidity Net
&lt;/li&gt;
&lt;li&gt;  ⚡️ Swap Code Summary
&lt;/li&gt;
&lt;li&gt;  ⚡️ Swap Contract Calls
&lt;/li&gt;
&lt;li&gt;  ⚡️ Difference between Exact Input and Output
&lt;/li&gt;
&lt;/ol&gt;




&lt;ul&gt;
&lt;li&gt;🏭 &lt;strong&gt;Factory&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;📊 &lt;strong&gt;Liquidity&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;  ⚡️ Tick Spacing
&lt;/li&gt;
&lt;li&gt;  ⚡️ NonfungiblePositionManager
&lt;/li&gt;
&lt;li&gt;  ⚡️ Adding Liquidity
&lt;/li&gt;
&lt;li&gt;  ⚡️ Removing Liquidity
&lt;/li&gt;
&lt;/ol&gt;




&lt;ul&gt;
&lt;li&gt;⚖️ &lt;strong&gt;Flash &amp;amp; Arbitrage&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;⏳ &lt;strong&gt;TWAP Price Oracle&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;  ⚡️ TWAP Math &lt;/li&gt;
&lt;li&gt;  ⚡️ TWAP Code &lt;/li&gt;
&lt;/ol&gt;




&lt;ul&gt;
&lt;li&gt;🎯 &lt;strong&gt;Just In Time Liquidity&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;







&lt;p&gt;&lt;a href="https://github.com/Cyfrin/advanced-defi-2024/blob/2c02a22513529666ac8f8545ac981fbae4107bc6/uniswap-v3.md" rel="noopener noreferrer"&gt;uniswap-v3.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/t4sk/clamm/tree/main" rel="noopener noreferrer"&gt;clamm&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🌟 Intro
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚡️ different between V2 V3
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxj7wkft21y4xyjtzvn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxj7wkft21y4xyjtzvn5.png" alt="Image description" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ concentrated liquidity
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fueosuu21uabvrwx5j0qo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fueosuu21uabvrwx5j0qo.png" alt="Image description" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;concentrated liquidity is to add liquidity for a certain &lt;strong&gt;price ranges&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The concentrated liquidity provision is similar to the "pending order", when the market price enters the user-set range, the liquidity will be automatically swapped. &lt;/li&gt;
&lt;li&gt;This mechanism allows LP to use capital more efficiently while "trading passively".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;position&lt;/strong&gt; = liquidity concentrated in a price range&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ liquidity price graph
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhthlx8dgcx5urd0xb1p4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhthlx8dgcx5urd0xb1p4.png" alt="Image description" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This graph represents the liquidity at each price, and at each price, liquidity is calculated by stacking up all of the position that overlaps with the price.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5o7ftlhhs6sj4ejcntmc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5o7ftlhhs6sj4ejcntmc.png" alt="Image description" width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To the left of the current price, all of the liquidity  is in Token Y(USDC), And to the right of the current price,liquidity  is all in token X.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1klp2bfmkyx6584pinw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz1klp2bfmkyx6584pinw.png" alt="Image description" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the price range you set does not include the current price, you can only add one token.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ V3 Contracts
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3kj5dt584825evvk9aq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3kj5dt584825evvk9aq.png" alt="Image description" width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now this Swap Router02 Contract has been upgraded to another&lt;br&gt;
contract inside the repository Uniswap Router. This Uniswap Router Contract is a more comprehensive contract that will allow you to swap between Uniswap V2, V3, and some NFTs.&lt;/p&gt;

&lt;p&gt;When call the function in V3pool, the caller must also be a smart contract.&lt;/p&gt;
&lt;h2&gt;
  
  
  🌐 Spot Price
&lt;/h2&gt;

&lt;p&gt;Because there may be multiple positions in different price ranges, you cannot just simply take the amount of token Y and the amount of token X in the contract to figure out what the spot price is.&lt;/p&gt;

&lt;p&gt;in uniswap V3 opposite of V2, it no longer keeps track of the amount of reserves, Instead, it keeps track of the current price, and from the current price, if we know the liquidity and the price ranges, then we can calculate the amount of tokens that must be locked in those price range.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bool zeroForOne = tokenIn &amp;lt; tokenOut&lt;/li&gt;
&lt;li&gt;zeroForOne:  0 -&amp;gt; 1 =&amp;gt; sqrt price decrease&lt;/li&gt;
&lt;li&gt;!zeroForOne: 1 -&amp;gt; 0 =&amp;gt; sqrt price increase &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  ⚡️ price and tick
&lt;/h3&gt;

&lt;p&gt;The way that the &lt;strong&gt;price&lt;/strong&gt; is stored inside Uniswap V3 is by this formula:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcc7h2lz9plhle7a9wiii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcc7h2lz9plhle7a9wiii.png" alt="Image description" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use one of sartPricex96 and tick can calculate the spot price.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;IUniswapV3Pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Slot0&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;slot0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;slot0&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// 1 / P = X / Y = USDC / WETH&lt;/span&gt;
&lt;span class="c1"&gt;//               = price of WETH in terms of USDC&lt;/span&gt;

&lt;span class="c1"&gt;// P has 1e18 / 1e6 = 1e12 decimals&lt;/span&gt;
&lt;span class="c1"&gt;// 1 / P has 1e6 / 1e18 = 1e-12 decimals&lt;/span&gt;

&lt;span class="c1"&gt;// sqrtPriceX96 * sqrtPriceX96 might overflow&lt;/span&gt;
&lt;span class="c1"&gt;// So use FullMath.mulDiv to do uint256 * uint256 / uint256 without overflow&lt;/span&gt;

&lt;span class="c1"&gt;// price = sqrt(P) * Q96 * sqrt(P) * Q96 / Q96&lt;/span&gt;
&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FullMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mulDiv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;slot0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sqrtPriceX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;slot0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sqrtPriceX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Q96&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 1 / price = 1 / (P * Q96)&lt;/span&gt;
&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;e12&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;e18&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="no"&gt;Q96&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📐 Math
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚡️ curve equation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8eu3l8mzmlourg18i29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft8eu3l8mzmlourg18i29.png" alt="Image description" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;equation&lt;/strong&gt; for x and y from liquidity and price.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Cyfrin/advanced-defi-2024/blob/2c02a22513529666ac8f8545ac981fbae4107bc6/excalidraw/amm/uniswap-v3/uniswap-v3-curve-real-reserves.png" rel="noopener noreferrer"&gt;curve of real reserves&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrssghy54nnsrp6ro102.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrssghy54nnsrp6ro102.png" alt="Image description" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q1:&lt;/strong&gt; &lt;a href="https://github.com/Cyfrin/advanced-defi-2024/blob/main/excalidraw/amm/uniswap-v3/uniswap-v3-xy-amounts.png" rel="noopener noreferrer"&gt;what is the +/- dx or dy after price change?&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="c1"&gt;/// @return amount0 Amount of currency0 required to cover a position of size liquidity between the two passed prices&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAmount0Delta&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtRatioAX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtRatioBX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint128&lt;/span&gt; &lt;span class="n"&gt;liquidity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;roundUp&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="nf"&gt;returns&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;/// @return amount1 Amount of currency1 required to cover a position of size liquidity between the two passed prices&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAmount1Delta&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtRatioAX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtRatioBX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint128&lt;/span&gt; &lt;span class="n"&gt;liquidity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;roundUp&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="nf"&gt;returns&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚡️ Price Delta
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvq62zglbq7t4nsznxy26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvq62zglbq7t4nsznxy26.png" alt="Image description" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2:&lt;/strong&gt; &lt;a href="https://github.com/Cyfrin/advanced-defi-2024/blob/2c02a22513529666ac8f8545ac981fbae4107bc6/excalidraw/amm/uniswap-v3/uniswap-v3-delta-price.png" rel="noopener noreferrer"&gt;what is the price change after +/- dx or dy?&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="c1"&gt;/// @notice Gets the next sqrt price given an input amount of currency0 or currency1&lt;/span&gt;
    &lt;span class="c1"&gt;/// @dev Throws if price or liquidity are 0, or if the next price is out of bounds&lt;/span&gt;
    &lt;span class="c1"&gt;/// @param sqrtPX96 The starting price, i.e., before accounting for the input amount&lt;/span&gt;
    &lt;span class="c1"&gt;/// @param liquidity The amount of usable liquidity&lt;/span&gt;
    &lt;span class="c1"&gt;/// @param amountIn How much of currency0, or currency1, is being swapped in&lt;/span&gt;
    &lt;span class="c1"&gt;/// @param zeroForOne Whether the amount in is currency0 or currency1&lt;/span&gt;
    &lt;span class="c1"&gt;/// @return sqrtQX96 The price after adding the input amount to currency0 or currency1&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getNextSqrtPriceFromInput&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtPX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint128&lt;/span&gt; &lt;span class="n"&gt;liquidity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amountIn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;zeroForOne&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="nf"&gt;returns&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtQX96&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getNextSqrtPriceFromOutput&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtPX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint128&lt;/span&gt; &lt;span class="n"&gt;liquidity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amountOut&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;zeroForOne&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="nf"&gt;returns&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtQX96&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚡️ Liquidity Delta
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wqu3i1v2vipo66mbmey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wqu3i1v2vipo66mbmey.png" alt="Image description" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3:&lt;/strong&gt; what is the liquidity after +/- dx or dy?&lt;/p&gt;

&lt;h2&gt;
  
  
  🎚️ Tick
&lt;/h2&gt;

&lt;p&gt;when you do a trade how does uniswap find the next position?&lt;/p&gt;

&lt;p&gt;it finds the next position is by recording the position stick lower and tick upper in a mapping called tick bitmap.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ tick bitmap
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypbdwh3xd69vpjcnlxrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypbdwh3xd69vpjcnlxrf.png" alt="Image description" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;tick bitmap is a mapping(From int16 to uint256) that stores the ticks that define the liquidity position.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tick&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;a tick basically is an int24 that splits into int16(key) and uint8(value).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to get tick from bitmap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;access the key fill up the first 16 bits access the index and then fill up the last 8 Bits.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ flip a tick
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchx9zbii229ba2w9nj1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fchx9zbii229ba2w9nj1z.png" alt="Image description" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ get Next tick
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcapw33zvh4d0mdmdx6t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcapw33zvh4d0mdmdx6t.png" alt="Image description" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💰 Fee Algorithm
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚡️ Fee Equation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmgv4dg2r66vtjtjdymt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkmgv4dg2r66vtjtjdymt.png" alt="Image description" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ek0k5a9ztcsx0d4soo1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ek0k5a9ztcsx0d4soo1.png" alt="Image description" width="800" height="501"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NOTE:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// fee growth += fee amount * (1 &amp;lt;&amp;lt; 128) / liquidity&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthGlobalX128&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nc"&gt;FullMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mulDiv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeAmount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;FixedPoint128&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Q128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;liquidity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/t4sk/clamm/blob/main/doc/clamm-11-calc-fee.png" rel="noopener noreferrer"&gt;calc-fee from liquidity and time&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ Fee Growth
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvttkporm0q27pai7py9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvttkporm0q27pai7py9.png" alt="Image description" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fee Growth inside&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;find the fee growth between I_lower and I_upper.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4ly8o2m55pooixkk8rc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4ly8o2m55pooixkk8rc.png" alt="Image description" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fee Growth Below&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwj7k4bqzi03hhmetjx2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwj7k4bqzi03hhmetjx2.png" alt="Image description" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foti6wuoizdudhq4ywzas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foti6wuoizdudhq4ywzas.png" alt="Image description" width="800" height="822"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fee Growth Above&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgo76bjh19oq4jq9q56zj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgo76bjh19oq4jq9q56zj.png" alt="Image description" width="800" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;in function Tick.getFeeGrowthInside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//NOTE: Calculate fee growth below&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;feeGrowthBelow0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;feeGrowthBelow1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tickLower&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;tickCurrent&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;feeGrowthBelow0X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;feeGrowthBelow1X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;feeGrowthBelow0X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal0X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;feeGrowthBelow1X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal1X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//NOTE: Calculate fee growth above&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;feeGrowthAbove0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;feeGrowthAbove1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tickCurrent&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;tickUpper&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;feeGrowthAbove0X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;feeGrowthAbove1X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;feeGrowthAbove0X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal0X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;feeGrowthAbove1X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal1X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚡️ Fee Growth Outside
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6bfivd28rmg0687ylws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6bfivd28rmg0687ylws.png" alt="Image description" width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It only change(flip) at the moment when i_c cross over the tick i.&lt;br&gt;
It always records f on the other side of i.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi40tvcts6wtaevvsyll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi40tvcts6wtaevvsyll.png" alt="Image description" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;initialize&lt;/strong&gt; in function Tick.update:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;liquidityGrossBefore&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// NOTE: initialize feeGrowthOutside&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO: why initialize below tick?&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;tickCurrent&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside0X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside1X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;update&lt;/strong&gt; in function Tick.cross:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside0X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal0X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside1X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal1X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthOutside1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;liquidityNet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;liquidityNet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚡️ Position fee
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56gih780mgqgpiyzcqct.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56gih780mgqgpiyzcqct.png" alt="Image description" width="800" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F587daxpldm0jkdu5ygmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F587daxpldm0jkdu5ygmw.png" alt="Image description" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how to calc fee inside position over a period of time.&lt;/p&gt;

&lt;p&gt;in function Tick.getFeeGrowthInside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//NOTE: Fee inside position (fee growth inside)&lt;/span&gt;
&lt;span class="n"&gt;feeGrowthInside0X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal0X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;feeGrowthBelow0X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;feeGrowthAbove0X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;feeGrowthInside1X128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feeGrowthGlobal1X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;feeGrowthBelow1X128&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;feeGrowthAbove1X128&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;both of them are Uninitialized&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq18m9qlc6f2cq32bxxjy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq18m9qlc6f2cq32bxxjy.png" alt="Image description" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;when f_out_lower/upper at t_i(time i) has not cross i_lower/upper, we &lt;strong&gt;initialize&lt;/strong&gt; it.&lt;/p&gt;

&lt;p&gt;when f_out_lower/upper at t_i(time i) crossed i_lower/upper, we &lt;strong&gt;update&lt;/strong&gt; it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fee Growth when one of them is initialized&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/t4sk/clamm/blob/main/doc/clamm-18-fee-growth-init-2.png" rel="noopener noreferrer"&gt;calculate F0-F2 when i_lower initialized and i_upper not initialized&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fee Growth when both of them are initialized&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzs8hmz1nt7i2dqobw8q7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzs8hmz1nt7i2dqobw8q7.png" alt="Image description" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ Fee code sum up
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Position.feeGrowthInside:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;calculate: &lt;code&gt;_updatePosition&lt;/code&gt; -&amp;gt; &lt;code&gt;Tick.getFeeGrowthInside&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// get fee growth inside&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;feeGrowthInside0X128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;feeGrowthInside1X128&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;ticks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getFeeGrowthInside&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tickLower&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tickUpper&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_feeGrowthGlobal0X128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_feeGrowthGlobal1X128&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// pass fee growth inside then calc tokensOwed&lt;/span&gt;
&lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;liquidityDelta&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feeGrowthInside0X128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;feeGrowthInside1X128&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tick.feeGrowthOutside:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;initialize: &lt;code&gt;_updatePosition&lt;/code&gt; -&amp;gt; &lt;code&gt;Tick.update&lt;/code&gt;&lt;br&gt;&lt;br&gt;
update: &lt;code&gt;swap&lt;/code&gt; -&amp;gt; &lt;code&gt;Tick.cross&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;clamm.feeGrowthGlobal:&lt;/strong&gt; Use for what? Where?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;initialize feeGrowthOutside: &lt;code&gt;_updatePosition&lt;/code&gt; -&amp;gt; &lt;code&gt;Tick.update&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;update Tick.feeGrowthOutside0X128: &lt;code&gt;swap&lt;/code&gt; -&amp;gt; &lt;code&gt;cross&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;calculate feeGrowthInside: &lt;code&gt;_updatePosition&lt;/code&gt; -&amp;gt; &lt;code&gt;Tick.getFeeGrowthInside&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;grow feeGrowthGlobal: &lt;code&gt;swap&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// fee growth += fee amount * (1 &amp;lt;&amp;lt; 128) / liquidity&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeGrowthGlobalX128&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nc"&gt;FullMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mulDiv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;feeAmount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;FixedPoint128&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Q128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;liquidity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  🔄 Swap
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ⚡️ liquidity net
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4oyga16v17wx4wdiskr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4oyga16v17wx4wdiskr9.png" alt="Image description" width="800" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The pink number is the liquidity net.&lt;/p&gt;

&lt;p&gt;To this current liquidity 13, we add [(+1)*(-10)] -&amp;gt; [direction*liquidity net] So the active liquidity when the current tick crosses over this tick(-10), must be equal to three.&lt;/p&gt;

&lt;p&gt;This was an example of how liquidity nets that are stored at the ticks keep track of the current liquidity. Every time the current tick crosses over one of these ticks, it will either add or minus some liquidity net to update the current liquidity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NOTE: liquidityNet (left +, right -)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zeroForOne&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;liquidityNet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;liquidityNet&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// How will liquidity change after crossing the current liquidityNet&lt;/span&gt;
&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;liquidityNet&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;uint128&lt;/span&gt;&lt;span class="o"&gt;(-&lt;/span&gt;&lt;span class="n"&gt;liquidityNet&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;uint128&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;liquidityNet&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚡️ Swap code sum up
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Cyfrin/advanced-defi-2024/blob/main/excalidraw/amm/uniswap-v3/uniswap-v3-swap-algo.png" rel="noopener noreferrer"&gt;uniswap-v3-swap-flow chart&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ Swap contract calls
&lt;/h3&gt;

&lt;p&gt;Know the recipient and payer of the process of Exact input and output, the flow of tokens in the intermediate process.&lt;/p&gt;

&lt;p&gt;Call the uniswapV3pool will recive token, then in the callback will pay the token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rs5ybz4qy2fcgyuqo51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rs5ybz4qy2fcgyuqo51.png" alt="Image description" width="711" height="797"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqa90iv1cxye5w14d9c4m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqa90iv1cxye5w14d9c4m.png" alt="Image description" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ the different between Exact input and output
&lt;/h3&gt;

&lt;p&gt;The order of path encoded of exact output is reverse compared to exact input (params.tokenIn, params.fee, params.tokenOut).&lt;/p&gt;

&lt;p&gt;When the function exact input is called, it will make a while loop call the internal function &lt;code&gt;exactOutputInternal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;the SwapRouter02 will receive token, then SwapRouter02 will pay for the callback.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// function exactInput:&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;payer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hasAlreadyPaid&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;hasMultiplePools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasMultiplePools&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// the outputs of prior swaps become the inputs to subsequent ones&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;amountIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exactInputInternal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;amountIn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;hasMultiplePools&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// for intermediate swaps, this contract custodies&lt;/span&gt;
        &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nc"&gt;SwapCallbackData&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;
            &lt;span class="nl"&gt;path:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getFirstPool&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// only the first pool in the path is necessary&lt;/span&gt;
            &lt;span class="nl"&gt;payer:&lt;/span&gt; &lt;span class="n"&gt;payer&lt;/span&gt;
        &lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// decide whether to continue or terminate&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hasMultiplePools&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;payer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// [A, fee, B, fee, C, fee, D] -&amp;gt; [B, fee, C, fee, D] -&amp;gt; [C, fee, D]&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;skipToken&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// [C, fee, D]&lt;/span&gt;
        &lt;span class="n"&gt;amountOut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;amountIn&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the function exact output is called, it will make a recursion at uniswapV3SwapCallback to recursive call into the internal function &lt;code&gt;exactOutputInternal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;the SwapRouter02 will set the recipient to the UniswapV3Pool from the previous recursive. In the next level of recursion, the next UniswapV3Pool will pay it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// function uniswapV3SwapCallback:&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isExactInput&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenIn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;payer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amountToPay&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// if is ExactOutput making a recursive call.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasMultiplePools&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//@ztmy remove the first token from the path.&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;skipToken&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;//@ztmy NOTE: making a recursive call.&lt;/span&gt;
        &lt;span class="c1"&gt;// Here message sender to this callback is the pool itself.&lt;/span&gt;
        &lt;span class="n"&gt;exactOutputInternal&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amountToPay&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;amountInCached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amountToPay&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="c1"&gt;// note that because exact output swaps are executed in reverse order, tokenOut is actually tokenIn&lt;/span&gt;
        &lt;span class="n"&gt;pay&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenOut&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;payer&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sender&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amountToPay&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🏭 Factory
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6v4ykpocv9akyn8d3h4n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6v4ykpocv9akyn8d3h4n.png" alt="Image description" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;all UniswapV3Pool contracts can be determined by these three inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  📊 Liquidity
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚡️ Tick Spacing
&lt;/h3&gt;

&lt;p&gt;Different tick spacing is allowed to adapt to different market requirements.Lower tick space means liquidity can be concentrated higher, at the cost of using more gas during the swap (more times to move the tick at a price range).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;USDC/DAI, tickSpacing = 1&lt;/li&gt;
&lt;li&gt;WETH/DAI, tickSpacing = 60&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚡️ NonfungiblePositionManager
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;mint&lt;/code&gt; -&amp;gt; &lt;code&gt;addLiquidity&lt;/code&gt; -&amp;gt; &lt;code&gt;pool.mint&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;increaseLiquidity&lt;/code&gt; -&amp;gt; &lt;code&gt;addLiquidity&lt;/code&gt; -&amp;gt; &lt;code&gt;pool.mint&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;decreaseLiquidity&lt;/code&gt; -&amp;gt; &lt;code&gt;pool.burn&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;collect&lt;/code&gt; -&amp;gt; &lt;code&gt;pool.burn&lt;/code&gt;(Calling burn only updates tokensOwed) -&amp;gt; &lt;code&gt;pool.collect&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚡️ add liquidity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;to call function &lt;code&gt;mint&lt;/code&gt; to add liquidity in NonfungiblePositionManager.sol.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;it mint NFT based on a tokenId as the index to mapping the position.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// function mint:&lt;/span&gt;
&lt;span class="n"&gt;_mint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;recipient&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_nextId&lt;/span&gt;&lt;span class="o"&gt;++));&lt;/span&gt;

&lt;span class="n"&gt;_positions&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tokenId&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Position&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;
    &lt;span class="nl"&gt;nonce:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;operator:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;poolId:&lt;/span&gt; &lt;span class="n"&gt;poolId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;tickLower:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tickLower&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;tickUpper:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tickUpper&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;liquidity:&lt;/span&gt; &lt;span class="n"&gt;liquidity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;feeGrowthInside0LastX128:&lt;/span&gt; &lt;span class="n"&gt;feeGrowthInside0LastX128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;feeGrowthInside1LastX128:&lt;/span&gt; &lt;span class="n"&gt;feeGrowthInside1LastX128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;tokensOwed0:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;tokensOwed1:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚡️ remove liquidity
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When the user calls the function &lt;code&gt;decreaseLiquidity&lt;/code&gt;, it calls the function &lt;code&gt;burn&lt;/code&gt; on Unisob B3 full contract, but no callback function to transferr token over to the user.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To actually transfer the tokens, the user will have to call another function &lt;code&gt;collect&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚖️ Flash &amp;amp; Arbitrage
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://solidity-by-example.org/defi/uniswap-v3-flash/" rel="noopener noreferrer"&gt;uniswap-v3-flash&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;UniswapV3FlashSwap.sol&lt;/code&gt; -&amp;gt; use function Flash to do a flash loan&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @ztmy in this contract, we borrow dai and repey, don't do arbitrage&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;flash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;encode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;FlashCallbackData&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;
            &lt;span class="nl"&gt;amount0:&lt;/span&gt; &lt;span class="n"&gt;amount0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;amount1:&lt;/span&gt; &lt;span class="n"&gt;amount1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// know who called into the function called Flash&lt;/span&gt;
            &lt;span class="nl"&gt;caller:&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sender&lt;/span&gt;
        &lt;span class="o"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;//---------------------- UNISWAP_V3 [borrow DAI] ------------------------&lt;/span&gt;
    &lt;span class="nc"&gt;IUniswapV3Pool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;flash&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="n"&gt;amount0&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;UniswapV3FlashSwapArbitrage.sol&lt;/code&gt; -&amp;gt; use function swap to do a flash loan&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Flash swap on pool0 (receive WETH)&lt;/span&gt;
&lt;span class="c1"&gt;// 2. Swap on pool1 (WETH -&amp;gt; DAI)&lt;/span&gt;
&lt;span class="c1"&gt;// 3. Repay pool0 with DAI&lt;/span&gt;
&lt;span class="c1"&gt;//---------------------- [borrow WETH from pool0] ------------------------&lt;/span&gt;
&lt;span class="c1"&gt;// here we call swap function which can do a flash loan same as function flash&lt;/span&gt;
&lt;span class="c1"&gt;// different between swap and flash when do a flash loan:&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Different parameter list&lt;/span&gt;
&lt;span class="c1"&gt;// 2. swap call uniswapV3SwapCallback with amount0, which is (amount0 + fee0)&lt;/span&gt;

&lt;span class="nc"&gt;IUniswapV3Pool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pool0&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;swap&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;
    &lt;span class="nl"&gt;recipient:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;zeroForOne:&lt;/span&gt; &lt;span class="n"&gt;zeroForOne&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;amountSpecified:&lt;/span&gt; &lt;span class="n"&gt;int256&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amountIn&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;sqrtPriceLimitX96:&lt;/span&gt; &lt;span class="n"&gt;sqrtPriceLimitX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;data:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="o"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⏳ TWAP Price Oracle
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ⚡️ Math TWAP
&lt;/h3&gt;

&lt;p&gt;In V2, TWAP is taken by &lt;code&gt;arithmetic mean&lt;/code&gt; of the prices.&lt;br&gt;
In V3, TWAP is taken by &lt;code&gt;geometric mean&lt;/code&gt; of the prices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tick Cumulative -&amp;gt; time weighted average tick -&amp;gt; TWAP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;tickCumulative_t+1 = tickCumulative_t + (tick_c × t_delta)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnww6hl35zhxqfizzuba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnww6hl35zhxqfizzuba.png" alt="Image description" width="800" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;in Uniswap V2, TWAP of token × and Y are not reciprocal:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F789dus0cyol1rqfy4301.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F789dus0cyol1rqfy4301.png" alt="Image description" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;when the spot price suddenly drops(left), TWAP calculated in V3 converges to the spot price than V2.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;when the spot price suddenly spikes up(right), TWAP calculated in V2 reacts quicker than V3.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7hmlo5jbo33z8e8s8ti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7hmlo5jbo33z8e8s8ti.png" alt="Image description" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚡️ Code Walkthrough Twap
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Oracle.sol&lt;/code&gt; -&amp;gt; &lt;code&gt;transform&lt;/code&gt;: calculate tickCumulative.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;observations.write&lt;/code&gt; -&amp;gt; &lt;code&gt;transform&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new observation'struct is saved whenever the liquidity or price changes by calling a function called &lt;code&gt;write&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;write&lt;/code&gt; is called at &lt;code&gt;_modifyPosition&lt;/code&gt; and &lt;code&gt;swap&lt;/code&gt; in pool contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;observe&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IUniswapV3Pool(pool).observe&lt;/code&gt; -&amp;gt; &lt;code&gt;observations.observe&lt;/code&gt; -&amp;gt; &lt;code&gt;observeSingle&lt;/code&gt; -&amp;gt; &lt;code&gt;transform&lt;/code&gt;, &lt;code&gt;getSurroundingObservations&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @ztmy call to get the tick cumulative.&lt;/span&gt;
&lt;span class="c1"&gt;// For the input you re passing an array of seconds, seconds ago from now.&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint32&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;secondsAgos&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;external&lt;/span&gt;
    &lt;span class="n"&gt;view&lt;/span&gt;
    &lt;span class="n"&gt;override&lt;/span&gt;
    &lt;span class="n"&gt;noDelegateCall&lt;/span&gt;
    &lt;span class="nf"&gt;returns&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int56&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;tickCumulatives&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint160&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;secondsPerLiquidityCumulativeX128s&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;observations&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;observe&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;_blockTimestamp&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;secondsAgos&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;slot0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tick&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;slot0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;observationIndex&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;liquidity&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;slot0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;observationCardinality&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OracleLibrary.sol&lt;/code&gt; -&amp;gt; &lt;code&gt;consult&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;//@ztmy this function will do is return the average tick over some time duration.&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;consult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint32&lt;/span&gt; &lt;span class="n"&gt;secondsAgo&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;internal&lt;/span&gt;
    &lt;span class="n"&gt;view&lt;/span&gt;
    &lt;span class="nf"&gt;returns&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int24&lt;/span&gt; &lt;span class="n"&gt;arithmeticMeanTick&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint128&lt;/span&gt; &lt;span class="n"&gt;harmonicMeanLiquidity&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;getQuoteAtTick&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tick: TWAT (time weighed average tick)&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getQuoteAtTick&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int24&lt;/span&gt; &lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint128&lt;/span&gt; &lt;span class="n"&gt;baseAmount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;baseToken&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;quoteToken&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;internal&lt;/span&gt;
    &lt;span class="n"&gt;pure&lt;/span&gt;
    &lt;span class="nf"&gt;returns&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;quoteAmount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Calculate sqrtRatioX96&lt;/span&gt;
    &lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;sqrtRatioX96&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TickMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getSqrtRatioAtTick&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sqrtRatioX96&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint128&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;ratioX192&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sqrtRatioX96&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sqrtRatioX96&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;quoteAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;baseToken&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;quoteToken&lt;/span&gt;
            &lt;span class="c1"&gt;// @ztmy&lt;/span&gt;
            &lt;span class="c1"&gt;// P = ratioX192 = (3000 USDC / 1 ETH), baseAmount = 1&lt;/span&gt;
            &lt;span class="c1"&gt;// P * baseAmount = (3000 USDC / 1 ETH) * 1 = 3000 USDC&lt;/span&gt;
            &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;FullMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mulDiv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ratioX192&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baseAmount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;// P = 1 / ratioX192, baseAmount = 6000 USDC&lt;/span&gt;
            &lt;span class="c1"&gt;// baseAmount / ratioX192 = 6000 USDC * (1 ETH / 3000 USDC) = 2 ETH&lt;/span&gt;
            &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FullMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mulDiv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;192&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baseAmount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ratioX192&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;ratioX128&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FullMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mulDiv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sqrtRatioX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sqrtRatioX96&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;quoteAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;baseToken&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;quoteToken&lt;/span&gt;
            &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nc"&gt;FullMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mulDiv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ratioX128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baseAmount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;FullMath&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;mulDiv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baseAmount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ratioX128&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🎯 Just In Time Liquidity
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Cyfrin/advanced-defi-2024/blob/main/excalidraw/amm/uniswap-v3/uniswap-v3-jit.png" rel="noopener noreferrer"&gt;What Is Just In Time Liquidity?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Justin sees that Bob has submitted a transaction to do a trade, then front runs the transaction to add liquidity so that he can earn a lot of fees.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>✨ Curve V1 notes</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Sat, 15 Mar 2025 14:59:16 +0000</pubDate>
      <link>https://dev.to/zt_myo/curve-v1-notes-17c2</link>
      <guid>https://dev.to/zt_myo/curve-v1-notes-17c2</guid>
      <description>&lt;h2&gt;
  
  
  Curve V1 equation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4zgh7vk1x3xnibc7vr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4zgh7vk1x3xnibc7vr9.png" alt="Image description" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;a curve that is in between constant sum and constant product.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A parameter controls how flat this curve B1 curb is (like the constant sum). &lt;/li&gt;
&lt;li&gt;Usually the a parameter is a fixed number however an admin can decide to change to a new A parameter, this change will take overtime. &lt;/li&gt;
&lt;li&gt;to put this point back on the curb what we had to do is find the new liquidity D, this process is not done all at once, but instead passes in the gradually changing value of A each time get_D is called.&lt;/li&gt;
&lt;li&gt;every time token balances changed, we will recalculate D.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#@ztmy
# What is D?
# Each token balance is D / N when the pool is perfectly balanced
# D is repreeent ideal liquidity (The sum of the balance is the actual liquidity), 
# It is the optimal balance point that Curve thinks the pool should reach.
&lt;/span&gt;
&lt;span class="c1"&gt;# D=f(balances,A)
# everytime calculate case of we need to use D, it update A by the way.
&lt;/span&gt;
&lt;span class="c1"&gt;# it's going to perform the Newton's method to calculate the value D
# xp: each token balance
# amp: self._A() to put in a gradually changing value of A 
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;N_COINS&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Contract overview
&lt;/h2&gt;

&lt;p&gt;all of the stable swap contracts will have five functions that are common:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;exchange&lt;/li&gt;
&lt;li&gt;add_liquidity&lt;/li&gt;
&lt;li&gt;remove_liquidity&lt;/li&gt;
&lt;li&gt;remove_liquidity_imbalance&lt;/li&gt;
&lt;li&gt;remove liquidity_one_coin&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Code walkthrough :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ramp_A&lt;/li&gt;
&lt;li&gt;stop_ramp_A&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;get_D&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;D=f(balances,A): everytime calculate case of we need to use D, it update A by the way.&lt;/p&gt;

&lt;p&gt;used at def get_y, add_liquidity&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;get_y&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;calculate the amounts y of j is changed by the input x of asset i.&lt;/p&gt;

&lt;p&gt;used at def get_dy, exchange&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;get_y_D&lt;/strong&gt;: &lt;/p&gt;

&lt;p&gt;calculate when D0 -&amp;gt; D1, How many the only one token y amount changed.&lt;/p&gt;

&lt;p&gt;used at def _calc_withdraw_one_coin&lt;/p&gt;

&lt;h2&gt;
  
  
  Exchange
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh5zirw9wwrr92i2x6t8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh5zirw9wwrr92i2x6t8m.png" alt="Image description" width="741" height="579"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@ztmy&lt;/span&gt;
&lt;span class="c1"&gt;# i and j represent the Token index of the transaction
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;int128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;int128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_dy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Handling an unexpected charge of a fee on transfer (USDT)
&lt;/span&gt;    &lt;span class="n"&gt;dx_w_fee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;
    &lt;span class="n"&gt;input_coin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coins&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# @ztmy
&lt;/span&gt;    &lt;span class="c1"&gt;# FEE_INDEX: constant(int128) = 2  # Which coin may potentially have fees (USDT)
&lt;/span&gt;    &lt;span class="c1"&gt;# like DAI that does not have fee on transfer, dx_w_fee == dx
&lt;/span&gt;    &lt;span class="c1"&gt;# however for tokens with transfer fee we need to 
&lt;/span&gt;    &lt;span class="c1"&gt;# balance of the token before transfer from - after transfer from = actual amount of tokens that came in
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;FEE_INDEX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;dx_w_fee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ERC20&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_coin&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;balanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some ERC20 tokens automatically charge a transfer fee when they are transferred.This fee is not charged by Curve itself, is deducted automatically by certain ERC20 token contracts when they do transferFrom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# "safeTransferFrom" which works for ERC20s which return bool or not
# @ztmy
# using a low level call to avoid the problem of 
# calling the function transferFrom() from both for tokens like DAI that returns a bool 
# and tokens like usdt does not return a bool
# through whether the response length is greater than 0
&lt;/span&gt;&lt;span class="n"&gt;_response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;raw_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;input_coin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;method_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transferFrom(address,address,uint256)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;max_outsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# dev: failed transfer
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# dev: failed transfer
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;get_dy&lt;/strong&gt;: Quotation stage, Check estimated prices. used for intra-contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;get_dy_underlying&lt;/strong&gt;: used for user. Return Real token unit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;exchange&lt;/strong&gt;: Execute a trade.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  add liquidity
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o2spanqci95d7pc5nho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o2spanqci95d7pc5nho.png" alt="Image description" width="731" height="646"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;to discourage users from imbalancing the pools there is an &lt;strong&gt;imbalance fee&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N_COINS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;#@ztmy this is the ideal balance increment for each token
&lt;/span&gt;    &lt;span class="n"&gt;ideal_balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;D1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;old_balances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;D0&lt;/span&gt;
    &lt;span class="n"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; 
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ideal_balance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;new_balances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ideal_balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;new_balances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_balances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ideal_balance&lt;/span&gt;
    &lt;span class="c1"&gt;# this is the imbalance fee that will be charged for each token
&lt;/span&gt;    &lt;span class="n"&gt;fees&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_fee&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;FEE_DENOMINATOR&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_balances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fees&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;_admin_fee&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;FEE_DENOMINATOR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;new_balances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;fees&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;D2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_D_mem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_balances&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the ideal balances are calculated by taking this ratio of the changing liquidity and then multiplying it by the previous token balances.&lt;/p&gt;

&lt;h2&gt;
  
  
  remove_liquidity
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8r64his3rghetlnk2mh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8r64his3rghetlnk2mh0.png" alt="Image description" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  remove_liquidity_one_coin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdhqurcusx1s07nf2fjv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdhqurcusx1s07nf2fjv.png" alt="Image description" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5c6sq111s2ddfdvfv9v6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5c6sq111s2ddfdvfv9v6.png" alt="Image description" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remove liquidity, D decreases. Just take out y, and x doesn't change, dy is the amount of y take out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# @ztmy for the output it's going to calculate the amount the token that you will receive and the fees.
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_calc_withdraw_one_coin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_token_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;int128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_A&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;_fee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fee&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;N_COINS&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N_COINS&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;precisions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;N_COINS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PRECISION_MUL&lt;/span&gt;
    &lt;span class="n"&gt;total_supply&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;totalSupply&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;N_COINS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_xp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;D0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;D0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;_token_amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;D0&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total_supply&lt;/span&gt;
&lt;span class="n"&gt;xp_reduced&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;N_COINS&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt;
&lt;span class="c1"&gt;# @ztmy calculate when D0 -&amp;gt; D1, and only one token amount changes y0
&lt;/span&gt;&lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_y_D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;dy_0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;precisions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# w/o fees
&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N_COINS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;dx_expected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="c1"&gt;# @ztmy
&lt;/span&gt;    &lt;span class="c1"&gt;# taking the the difference this will give us 
&lt;/span&gt;    &lt;span class="c1"&gt;# the difference from The ideal Balance of j after removing liquidity (xp[j] * D1 / D0)
&lt;/span&gt;    &lt;span class="c1"&gt;# and the actual amount after removing liquidity
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;dx_expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;D1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;D0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;dx_expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;xp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;D1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;D0&lt;/span&gt;
        &lt;span class="c1"&gt;#@ztmy the Imbalance Fee is paid only in the currency of withdrawal, 
&lt;/span&gt;        &lt;span class="c1"&gt;# and the Imbalance Fee in other currencies is deducted directly from the pool
&lt;/span&gt;    &lt;span class="n"&gt;xp_reduced&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;_fee&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dx_expected&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;FEE_DENOMINATOR&lt;/span&gt;

&lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xp_reduced&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_y_D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;xp_reduced&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>✨ Uniswap V2 notes</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Sat, 15 Mar 2025 09:31:28 +0000</pubDate>
      <link>https://dev.to/zt_myo/uniswap-v2-nodes-3dk7</link>
      <guid>https://dev.to/zt_myo/uniswap-v2-nodes-3dk7</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/Cyfrin/advanced-defi-2024/blob/2c02a22513529666ac8f8545ac981fbae4107bc6/uniswap-v2.md" rel="noopener noreferrer"&gt;uniswap-v2.md&lt;/a&gt;&lt;br&gt;
&lt;a href="https://youtu.be/t0NZq8SmywU" rel="noopener noreferrer"&gt;https://youtu.be/t0NZq8SmywU&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  contract overview
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Factory&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pair&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;add remove liquidity and swap tokens&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;router&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;is an intermediate contract between the user and the pair contracts the main job of the router contract is to safely add remove liquidity from the pair contracts and also safely swap tokens with the pair contracts.&lt;/p&gt;

&lt;p&gt;the router contract is a useful contract if we have to do multiple hop swaps&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code repos:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;v2-core &lt;/p&gt;

&lt;p&gt;v2-periphery&lt;/p&gt;
&lt;h2&gt;
  
  
  swap
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxam7lmes4owme2l9aw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxam7lmes4owme2l9aw4.png" alt="Image description" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;swapExactTokensForTokens() -&amp;gt; getAmountsOut()&lt;/p&gt;

&lt;p&gt;swapTokensForExactTokens() -&amp;gt; getAmountsIn()&lt;/p&gt;

&lt;p&gt;How to directly call the swap in pair contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//@ztmy before directly call the pair contract instead of calling the router contract:&lt;/span&gt;
&lt;span class="c1"&gt;// 1. transfer token to pair&lt;/span&gt;
&lt;span class="c1"&gt;// 2. excute UniswapV2Library.getAmountsOut to calculate the amount0Out, amount1Out&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amountOut&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isZeroForOne&lt;/span&gt;
    &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;getAmountOut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amountOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reserve1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reserve0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;getAmountOut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amountOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reserve0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reserve1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// transfer eth borrow form loan swap to pair1&lt;/span&gt;
&lt;span class="n"&gt;IERC20&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenOut&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pair1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amountOut&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// git DAI form pair1&lt;/span&gt;
&lt;span class="n"&gt;IUniswapV2Pair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pair1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nl"&gt;amount0Out:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isZeroForOne&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;amountOut&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 10682631633961643998417&lt;/span&gt;
    &lt;span class="nl"&gt;amount1Out:&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isZeroForOne&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amountOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0&lt;/span&gt;
    &lt;span class="nl"&gt;to:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;data:&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;spot price&lt;/strong&gt; (mid price) = current price = X0 / Y0&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;execution price:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fe4szsnnu1v7zhcyb8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8fe4szsnnu1v7zhcyb8z.png" alt="Image description" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cause of &lt;strong&gt;slippage&lt;/strong&gt;: Market movement&lt;/p&gt;

&lt;h2&gt;
  
  
  createPair
&lt;/h2&gt;

&lt;p&gt;1 byte=8 bits=2 hex characters&lt;/p&gt;

&lt;p&gt;Ethereum address length = 20 bytes = 40 hexadecimal characters = a large decimal integer of more than 48 bits&lt;/p&gt;

&lt;p&gt;to make sure that the UniswapV2Pair contract is only dependent on token0, token1 that it can be calculated from token0 and token1, for the UniswapV2Pair contract Constructor argument it passes nothing, it will call a function called initialize to set token0, token1.&lt;/p&gt;

&lt;h2&gt;
  
  
  add liquidity
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg75bamoxrqd2j8ttel1r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg75bamoxrqd2j8ttel1r.png" alt="Image description" width="800" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the amount of tokens inside this AMM is described by this point.&lt;/p&gt;

&lt;p&gt;when we're adding liquidity is that the resulting amount of token X and token y most must be along this line.&lt;/p&gt;

&lt;p&gt;three way to define the pool value:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrqkxs3xvv88zijhv72v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmrqkxs3xvv88zijhv72v.png" alt="Image description" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;get pool shares after add liquidity:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zaw6pyc0hopiuk5eytc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zaw6pyc0hopiuk5eytc.png" alt="Image description" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Flash swap (Flash loan)
&lt;/h2&gt;

&lt;p&gt;Flash swap fee derives from swap fee.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivpg171ga111wl34psdb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivpg171ga111wl34psdb.png" alt="Image description" width="800" height="488"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Uniswap V2 callback&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;IUniswapV2Callee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;uniswapV2Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount0Out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount1Out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the danger of amm's spot price as a price oricle was Spot price manipulation.&lt;/p&gt;

&lt;h2&gt;
  
  
  TWAP-(time weighted average price)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1te4fa35eomixhp36in.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1te4fa35eomixhp36in.png" alt="Image description" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cumulative price&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;using cumulative price to calculate the TWAP&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtrj6w3ktc3gab9lgtre.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frtrj6w3ktc3gab9lgtre.png" alt="Image description" width="800" height="485"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uint256(uint224(y) * 2**112 / uint224(x)) = (y / x) * 2^112
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fixed-Point Number&lt;/strong&gt; is a method of representing decimal numbers using integers.used to simulate decimal arithmetic in systems (such as Solidity) that do not support floating-point arithmetic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arbitrage
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptk2269wfng8n2pepp31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptk2269wfng8n2pepp31.png" alt="Image description" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UniswapV2Arb1&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;execute Arbitrage between three UniswapV2Pair contracts&lt;/li&gt;
&lt;li&gt;model_1 in uniswap_v2_arb.png(borrow DAI and return DAI)&lt;/li&gt;
&lt;li&gt;The swap fee is calculated at the end.&lt;/li&gt;
&lt;li&gt;in this exercise we'll calling the router contract(swapExactTokensForTokens)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;UniswapV2Arb2&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;execute Arbitrage between two UniswapV2Pair contracts&lt;/li&gt;
&lt;li&gt;model_1 in uniswap_v2_arb.png(borrow ETH and return DAI)&lt;/li&gt;
&lt;li&gt;The swap fee calculation is included in the borrowing process(getAmountOut).&lt;/li&gt;
&lt;li&gt;in this exercise we'll need to directly call the pair contract instead of calling the router contract.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Arbitrage Optimal Amount In&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fped4hd2pty0wpekl5t02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fped4hd2pty0wpekl5t02.png" alt="Image description" width="800" height="687"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🚀Learn The Ultimate Stack for Web3 Development:🔥 Next.js + RainbowKit + wagmi + viem</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Wed, 12 Mar 2025 13:47:46 +0000</pubDate>
      <link>https://dev.to/zt_myo/learn-the-ultimate-stack-for-web3-development-nextjs-rainbowkit-wagmi-viem-4fn8</link>
      <guid>https://dev.to/zt_myo/learn-the-ultimate-stack-for-web3-development-nextjs-rainbowkit-wagmi-viem-4fn8</guid>
      <description>&lt;p&gt;&lt;strong&gt;Next.js&lt;/strong&gt;: &lt;br&gt;
Server-side rendering, API routes, and seamless React integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RainbowKit&lt;/strong&gt;: &lt;br&gt;
Beautiful, customizable wallet connection UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;wagmi&lt;/strong&gt;: &lt;br&gt;
Simplified Ethereum interactions with React Hooks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;viem&lt;/strong&gt;: &lt;br&gt;
Lightweight, type-safe, and highly performant Ethereum library.&lt;/p&gt;
&lt;h2&gt;
  
  
  Project:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;gtaNFT&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;
  
  
  gtaNFT
&lt;/h1&gt;

&lt;p&gt;🔹.__&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>nextjs</category>
      <category>react</category>
      <category>web3</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>🚀 From Zero to a Web3 Developer 🔥 Ethers &amp; Hardhat Bootcamp ⚡ Daily Updates &amp; Code!</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Thu, 06 Mar 2025 16:21:49 +0000</pubDate>
      <link>https://dev.to/zt_myo/from-zero-to-a-web3-developer-ethers-hardhat-bootcamp-daily-updates-code-4foh</link>
      <guid>https://dev.to/zt_myo/from-zero-to-a-web3-developer-ethers-hardhat-bootcamp-daily-updates-code-4foh</guid>
      <description>&lt;h2&gt;
  
  
  This series of learning plans:
&lt;/h2&gt;

&lt;p&gt;fist and formost,I want to say thinks to Patrick Collins for this fantastic course &lt;br&gt;
&lt;a href="https://youtu.be/gyMwXuJrbJQ" rel="noopener noreferrer"&gt;Full Stack Web3 Development with JavaScript&lt;/a&gt;&lt;br&gt;&lt;br&gt;
The learning plan was to learn some lessons of this course:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;★ Ethers.js Simple Storage
&lt;/li&gt;
&lt;li&gt;★ Hardhat Simple Storage
&lt;/li&gt;
&lt;li&gt;★ Hardhat Fund Me
&lt;/li&gt;
&lt;li&gt;★ NextJS Smart Contract Lottery (Full Stack)
&lt;/li&gt;
&lt;li&gt;★ [Hardhat DeFi &amp;amp; Aave]&lt;/li&gt;
&lt;li&gt;★ NextJS NFT Marketplace (Full Stack)&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Daily Updates Include:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;New knowledge encountered in today's study -→ 📌 harvest&lt;/li&gt;
&lt;li&gt;My practice (if I had done it)             -→ 📌 practice&lt;/li&gt;
&lt;li&gt;learning summary and feelings              -→ 📌 sum &amp;amp; F&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a id="lesson-1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  lesson 1
&lt;/h2&gt;
&lt;h3&gt;
  
  
  5 Mar:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://ethervm.io/decompile" rel="noopener noreferrer"&gt;decompile bytecode&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.ethers.org/" rel="noopener noreferrer"&gt;docs.ethers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;use private key in js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PRIVATE_KEY_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;password node deploy.js
// clear &lt;span class="nb"&gt;history
history&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;build a script to encrypt our private key.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;transaction response and transaction receipts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deploymentReceipt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForDeployment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Contract deployed to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//   @ztmy&lt;/span&gt;
&lt;span class="c1"&gt;//   transaction receipts and transaction response are different.&lt;/span&gt;
&lt;span class="c1"&gt;//   receipt is what you get when you wait for a transaction to finish. &lt;/span&gt;
&lt;span class="c1"&gt;//   And then response is just what you initially get.&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Here is the transaction:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploymentTransaction&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Here is the receipt:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deploymentReceipt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;create a task&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// create a tesk at tesks folder&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat/config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;block-number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Prints the current block number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="c1"&gt;// @ztmy hre: hardhat runtime environment&lt;/span&gt;
  &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blockNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBlockNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Current block number: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;blockNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// hardhat.config.js
// import this task
require("./tasks/block-number")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn hardhat block-number &lt;span class="nt"&gt;--network&lt;/span&gt; rinkeby
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;scripts and tasks both can basically do the same thing.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;hardhat node&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# start a local hardhat test net&lt;/span&gt;
yarn hardhat node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://127.0.0.1:8545&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;31337&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;hardhat console&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn hardhat console &lt;span class="nt"&gt;--net&lt;/span&gt; work localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can do anything in these consoles(terminal), and they're great ways to quickly test and tinker in interact with contracts.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 2
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6 Mar:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;hardhat unit test&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// describe("SimpleStorage", () =&amp;gt; {})&lt;/span&gt;
&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SimpleStorage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;simpleStorageFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;simpleStorage&lt;/span&gt;
  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;simpleStorageFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SimpleStorage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;simpleStorage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;simpleStorageFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="c1"&gt;// @ ztmy write a unit test&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should start with a favorite number of 0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;simpleStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expectedValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="c1"&gt;// assert&lt;/span&gt;
    &lt;span class="c1"&gt;// expect&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;expectedValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// expect(currentValue.toString()).to.equal(expectedValue)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;run only specific tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn hardhat &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--grep&lt;/span&gt; store
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// use only keyword&lt;/span&gt;
&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;only&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Should start with a favorite number of 0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;gas reporter &amp;amp; coinmarketcap&lt;/em&gt; -&amp;gt;[t=34730]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;gasReporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;outputFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gas-report.txt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;noColors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// has the USD price of each one of these transactions&lt;/span&gt;
    &lt;span class="nx"&gt;coinmarketcap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;COINMARKETCAP_API_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.npmjs.com/package/hardhat-gas-reporter" rel="noopener noreferrer"&gt;hardhat-gas-reporter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;coverage&lt;/em&gt; -&amp;gt; [t=35080]&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-3"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 3
&lt;/h2&gt;

&lt;p&gt;🔹.&lt;em&gt;use hardhat to deploy&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FundMe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ethUsdPriceFeedAddress&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// we need to wait if on a live network so we can verify properly&lt;/span&gt;
    &lt;span class="na"&gt;waitConfirmations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blockConfirmations&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;get recent deoploy &amp;amp; connect&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// To get the most recently deployed instance, you'll need the deployed addresses&lt;/span&gt;
&lt;span class="c1"&gt;// You might need to get these from your deployment artifacts or a helper function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fundMeDeployment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FundMe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mockV3AggregatorDeployment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MockV3Aggregator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Connect to the deployed contracts with the deployer as signer&lt;/span&gt;
&lt;span class="nx"&gt;fundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;FundMeFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fundMeDeployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;deployer&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;mockV3Aggregator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;MockV3AggregatorFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;mockV3AggregatorDeployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sets the signer (wallet) that will be used when sending transactions to this contract. The "deployer" variable is typically a wallet/signer object. When you call methods on this contract that change state (non-view functions), they'll be signed by this deployer account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @ztmy connect to other address to test require ower.&lt;/span&gt;
&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Only allows the owner to withdraw&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSigners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fundMeConnectedContract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fundMeConnectedContract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revertedWithCustomError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FundMe__NotOwner&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;Staging Tests&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Staging Tests - Need to be run on an actual test network, such as Sepolia.&lt;/span&gt;
&lt;span class="nx"&gt;developmentChains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;skip&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FundMe Staging Tests&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// Unit Tests - run only on local hardhat or localhost.&lt;/span&gt;
&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;developmentChains&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;skip&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FundMe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Staging : Testing our code in a real environment that is not prod.this is the last step in your development journey.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-4"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 4
&lt;/h2&gt;

&lt;h3&gt;
  
  
  7 Mar:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;Common contract-related Ethers operations&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get contract factories&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ContractFactory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contract&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="c1"&gt;// Get deployment Information&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ContractDeployment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contract&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="c1"&gt;// Get contract instance&lt;/span&gt;
&lt;span class="nx"&gt;Contract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contract&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ContractDeployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Connect to the deployed contracts with the deployer&lt;/span&gt;
&lt;span class="nx"&gt;fundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;get return from Event&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// create VRFV2 Subscription&lt;/span&gt;
&lt;span class="nx"&gt;VRFCoordinatorV2_5MockAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;VRFCoordinatorV2_5MockDeployment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transactionResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createSubscription&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;transactionReceipt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;transactionResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// @ztmy transaction After sending a transaction, we can only get a transaction response and cannot get the return value directly.&lt;/span&gt;
&lt;span class="c1"&gt;// @ztmy We can only find Events from the response to get these information&lt;/span&gt;

&lt;span class="c1"&gt;// Query events from the VRFCoordinatorV2_5Mock contract&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queryFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="c1"&gt;// - Use filters.SubscriptionCreated() to only get SubscriptionCreated events&lt;/span&gt;
    &lt;span class="nx"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SubscriptionCreated&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;subscriptionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  8 Mar:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;Moralis&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;enableWeb3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isWeb3Enabled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isWeb3EnableLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Moralis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deactivateWeb3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="nf"&gt;useMoralis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;lets front-end developers get on-chain data directly without running their own blockchain nodes&lt;/li&gt;
&lt;li&gt;provides Web3 login, wallet connection, transaction query and other functions to simplify dApp development&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But no longer update.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;web3uikit&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Beautiful and lightweight UI components for web3 developers.&lt;/p&gt;

&lt;p&gt;But no longer update, only support react 18.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Front-end stack&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React+Next.js&lt;/li&gt;
&lt;li&gt;Ethers.js/viem/web3j.s&lt;/li&gt;
&lt;li&gt;RainbowKit + wagmi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we can scaffold a RainbowKit(web3uikit) + wagmi(Moralis) + Next.js app as an alternative.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;create a update-front-end.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frontEndContractsFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../nextjs-smartcontract-lottery-fcc/constants/contractAddresses.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frontEndAbiFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../nextjs-smartcontract-lottery-fcc/constants/abi.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateAbi&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raffle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Raffle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frontEndAbiFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;raffle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormatTypes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;create a update-front-end.js under the deploy folder, when we redeployment contract, we can run this to automated the process of updating our contract information and pass them to front end codebase.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;the rest of work&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a hook entranceFee and show it.&lt;/li&gt;
&lt;li&gt;add notification provider.&lt;/li&gt;
&lt;li&gt;show numPlayers,recentWinner.&lt;/li&gt;
&lt;li&gt;run mockOffchain to test.&lt;/li&gt;
&lt;li&gt;use tailwindcss to Optimized style. -&amp;gt;[t=18.05.55] &lt;/li&gt;
&lt;li&gt;use fleek to deploy front end.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📌 sum &amp;amp; F&lt;/p&gt;

&lt;p&gt;I only learned the basic idea of making a front end, and I will use the latest set of dependencies in my later practice.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-5"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 5
&lt;/h2&gt;

&lt;h3&gt;
  
  
  9 Mar:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;Forking&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;hardhat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;chainId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;31337&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;forking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MAINNET_RPC_URL&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iWeth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IWeth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="c1"&gt;// @ztmy get Contract derictly from forked main net &lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;signer&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Pros: Quick, easy, resemble what's on mainnet &lt;/li&gt;
&lt;li&gt;Cons: We need an API, some contracts are complex to work with&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;hardhat-deploy&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;getNamedAccounts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getNamedAccounts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyContract&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;log&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// only execute deploy scripts with the given tags&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyContract&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;yarn add --dev hardhat-deploy&lt;/code&gt;&lt;br&gt;
We us hardhat-deploy to deploy contract, this is a community plugin.&lt;br&gt;
&lt;a href="https://hardhat.org/hardhat-runner/plugins#community-plugins" rel="noopener noreferrer"&gt;Community plugins&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Aave Borrow&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;getWeth&lt;/li&gt;
&lt;li&gt;getLendingPool&lt;/li&gt;
&lt;li&gt;approveErc20&lt;/li&gt;
&lt;li&gt;deposit&lt;/li&gt;
&lt;li&gt;getBorrowUserData&lt;/li&gt;
&lt;li&gt;getDaiPrice&lt;/li&gt;
&lt;li&gt;borrowDai&lt;/li&gt;
&lt;li&gt;getBorrowUserData&lt;/li&gt;
&lt;li&gt;repay&lt;/li&gt;
&lt;li&gt;getBorrowUserData&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a id="lesson-5"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  lesson 5
&lt;/h2&gt;
&lt;h3&gt;
  
  
  9 Mar:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.__&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.__&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.__&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.__&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.__&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>etherjs</category>
      <category>hardhat</category>
    </item>
    <item>
      <title>🚀 From Zero to a Web3 Developer 🔥 Solidity &amp; Foundry Bootcamp ⚡ Daily Updates &amp; Code!</title>
      <dc:creator>MY ZT</dc:creator>
      <pubDate>Wed, 12 Feb 2025 14:27:09 +0000</pubDate>
      <link>https://dev.to/zt_myo/immersed-in-studying-solidityfoundry-with-me-full-time-and-updated-daily-4j47</link>
      <guid>https://dev.to/zt_myo/immersed-in-studying-solidityfoundry-with-me-full-time-and-updated-daily-4j47</guid>
      <description>&lt;h2&gt;
  
  
  This Series of Learning Plans
&lt;/h2&gt;

&lt;p&gt;First and foremost, I want to say thanks to Patrick Collins for this fantastic course: &lt;a href="https://youtu.be/-1GB6m39-rM?si=shn6Cf4sbw6fUkEV" rel="noopener noreferrer"&gt;Learn Solidity Smart Contract Development&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
This learning plan is based on the outline of his course.&lt;/p&gt;
&lt;h3&gt;
  
  
  1 Solidity - Remix
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;★ | 2 | Remix - Simple Storage
&lt;/li&gt;
&lt;li&gt;★ | 3 | Storage Factory
&lt;/li&gt;
&lt;li&gt;★ | 4 | Fund Me
&lt;/li&gt;
&lt;li&gt;★ | 5 | AI Prompting &lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  2 Solidity - Foundry
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;★ | 6 | Foundry Simple Storage
&lt;/li&gt;
&lt;li&gt;★ | 7 | Foundry Fund Me &lt;/li&gt;
&lt;li&gt;★ | 8 | HTML Fund Me
&lt;/li&gt;
&lt;li&gt;★ | 9 | Foundry Smart Contract Lottery
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  3 Solidity - Advanced Foundry
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;★ | 10 | ERC20s
&lt;/li&gt;
&lt;li&gt;★ | 11 | NFTs
&lt;/li&gt;
&lt;li&gt;★ | 12 | DeFi Stablecoin
&lt;/li&gt;
&lt;li&gt;★ | 13 | Merkle Trees and Signatures
&lt;/li&gt;
&lt;li&gt;★ | 14 | Upgradable Smart Contracts
&lt;/li&gt;
&lt;li&gt;★ | 15 | Account Abstraction
&lt;/li&gt;
&lt;li&gt;★ | 16 | DAOs
&lt;/li&gt;
&lt;li&gt;★ | 17 | Security Introduction
&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Daily Updates Include:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;New knowledge encountered in today's study -→ 📌 harvest&lt;/li&gt;
&lt;li&gt;My practice (if I had done it)             -→ 📌 practice&lt;/li&gt;
&lt;li&gt;Today's learning summary and feelings      -→ 📌 sum &amp;amp; F&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;a id="lesson-2-3"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  lesson 2-3
&lt;/h2&gt;
&lt;h3&gt;
  
  
  12 Feb:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;public&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;listOfPeople&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"public" keyword can create a getter function automatically.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;mapping&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;nameToFavoriteNumber&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;nameToFavoriteNumber&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_favoriteNumber&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;mapping is like a dictionary in python.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Factory contract&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createSimpleStorageContract&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;SimpleStorage&lt;/span&gt; &lt;span class="n"&gt;simpleStorageContractVariable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SimpleStorage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// SimpleStorage simpleStorage = new SimpleStorage();&lt;/span&gt;
        &lt;span class="n"&gt;listOfSimpleStorageContracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;simpleStorageContractVariable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;use a Factory contract to create and mange the SimpleStorage contract&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;inherit&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;AddFiveStorage&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;SimpleStorage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;_favoriteNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;myFavoriteNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_favoriteNumber&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;SimpleStorage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;_favoriteNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;myFavoriteNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_favoriteNumber&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;virtual: Function in the parent contract. If you want the subcontract to be overwritten, you need to add the virtual keyword.&lt;br&gt;
override:  The subcontract overwrites the function in the parent contract and requires the override keyword.&lt;/p&gt;

&lt;p&gt;🔹. &lt;em&gt;data storage&lt;/em&gt;&lt;br&gt;
There are three types of Solidity data storage locations: storage, memory, and calldata:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;storage (contract state variable) : The default state variable in the contract is storage, stored on the chain.&lt;/li&gt;
&lt;li&gt;memory: Parameters and temporary variables in a function are usually stored in memory and are not chained. In particular, if the returned data type is variable in length, memory modification must be added, such as: string, bytes, array, and custom structures.&lt;/li&gt;
&lt;li&gt;calldata: Similar to memory, it is stored in memory and is not linked. Unlike memory, the calldata variable is immutable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Actually, I learned solidity basics and install foundry about half a year ago when I was in university, but now I have almost forgotten everything. Now I am graduating and settling down to restart. Today is the first day, and I will persist in studying every day. &lt;/p&gt;

&lt;p&gt;Welcome everyone to follow my journey and learn with me!&lt;/p&gt;

&lt;p&gt;If you're also interested in Web3 technology, feel free to reach out—we can exchange ideas and grow together!&lt;/p&gt;



&lt;p&gt;&lt;a id="lesson-4-5"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  lesson 4-5
&lt;/h2&gt;
&lt;h3&gt;
  
  
  13 Feb:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;oracle&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kpn54mnaxjhssc5c5o6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kpn54mnaxjhssc5c5o6.png" alt="Image description" width="800" height="384"&gt;&lt;/a&gt;&lt;br&gt;
  chain link nodes each reaches out and gets the information about an asset and then signs the data with their own private key in a single transaction then one node will deliver all the data with all the different signatures to a reference contract.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getPrice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Sepolia ETH / USD Address&lt;/span&gt;
        &lt;span class="c1"&gt;// https://docs.chain.link/data-feeds/price-feeds/addresses&lt;/span&gt;
        &lt;span class="n"&gt;AggregatorV3Interface&lt;/span&gt; &lt;span class="n"&gt;priceFeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AggregatorV3Interface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="mh"&gt;0x694AA1769357215DE4FAC081bf1f309aDC325306&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;(,&lt;/span&gt; &lt;span class="n"&gt;int256&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latestRoundData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="c1"&gt;// ETH/USD rate in 18 digit&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;retrieves the latest price of Ethereum (ETH) in USD from a Chainlink price feed and returns the value.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;library&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before use library:&lt;/span&gt;
&lt;span class="n"&gt;getConversionRate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// create a library:&lt;/span&gt;
&lt;span class="n"&gt;library&lt;/span&gt; &lt;span class="n"&gt;PriceConverter&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;// use library for uint256:&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;PriceConverter&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getConversionRate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for uint256 This part says we're going to extend the functions in PriceConverter to uint256.&lt;br&gt;
so a uint256 variable can call a PriceConverter function as an object, just like a uint256 method itself. There is no need to explicitly pass parameters. &lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;constant &amp;amp; immutable&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;MINIMUM_USD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1e18110&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//21,415 gas -constant&lt;/span&gt;
&lt;span class="c1"&gt;//23,515 gas -non-constant&lt;/span&gt;
&lt;span class="c1"&gt;//21,415 * 141000000000 = $9.058545&lt;/span&gt;
&lt;span class="c1"&gt;//23,515 * 141000000000 = $9.946845&lt;/span&gt;

&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="cm"&gt;/* immutable */&lt;/span&gt; &lt;span class="n"&gt;i_owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you don't use the constant keyword in Solidity, the variable will use storage by default, gas is high not only when deployed, but also when the variable is fetched.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;constant: Applies to values that are determined at compile time.&lt;/li&gt;
&lt;li&gt;immutable: applies to variables that are determined at deployment time, but do not change thereafter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;modifier &amp;amp; custom errors&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// custom errors&lt;/span&gt;
&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="nf"&gt;NotOwner&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// modifier &lt;/span&gt;
    &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="nf"&gt;onlyOwner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// require(msg.sender == owner, "not owner");&lt;/span&gt;
        &lt;span class="c1"&gt;// call the error code as opposed to calling the entire string&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;i_owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;revert&lt;/span&gt; &lt;span class="n"&gt;NotOwner&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// use modifier to withdraw&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;onlyOwner&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;"_;" at the end means execute modifier first, then the part of the function that use this modifier.&lt;/li&gt;
&lt;li&gt;every characters in this error log needs to get stored individually.so call the error code as opposed to calling the entire string can save gas, since we don't have to store and emit this long string.&lt;/li&gt;
&lt;li&gt;revert is the same as require.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;SendETH&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// // transfer&lt;/span&gt;
&lt;span class="c1"&gt;// payable(msg.sender).transfer(address(this).balance);&lt;/span&gt;

&lt;span class="c1"&gt;// // send&lt;/span&gt;
&lt;span class="c1"&gt;// bool sendSuccess = payable(msg.sender).send(address(this).balance);&lt;/span&gt;
&lt;span class="c1"&gt;// require(sendSuccess, "Send failed");&lt;/span&gt;

&lt;span class="c1"&gt;// call&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;callSuccess&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Call failed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;There is no gas limit for call, which is the most flexible and recommended way;&lt;/li&gt;
&lt;li&gt;The gas limit of transfer is 2300 gas, transaction will be reverted if it fails;&lt;/li&gt;
&lt;li&gt;The gas limit of send is 2300, the transaction will not be reverted if it fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;receive &amp;amp; fallback&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;payable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fund&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;payable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fund&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Ether is sent to contract&lt;/span&gt;
    &lt;span class="c1"&gt;//      is msg.data empty?&lt;/span&gt;
    &lt;span class="c1"&gt;//          /   \&lt;/span&gt;
    &lt;span class="c1"&gt;//         yes  no&lt;/span&gt;
    &lt;span class="c1"&gt;//         /     \&lt;/span&gt;
    &lt;span class="c1"&gt;//    receive()?  fallback()&lt;/span&gt;
    &lt;span class="c1"&gt;//     /   \&lt;/span&gt;
    &lt;span class="c1"&gt;//   yes   no&lt;/span&gt;
    &lt;span class="c1"&gt;//  /        \&lt;/span&gt;
    &lt;span class="c1"&gt;//receive()  fallback()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹🔹🔹.&lt;em&gt;ERC-2335&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# create defaultKey&lt;/span&gt;
cast wallet import defaultKey &lt;span class="nt"&gt;--interactive&lt;/span&gt;
&lt;span class="c"&gt;# see defaultKey&lt;/span&gt;
cast wallet list
&lt;span class="c"&gt;# here you can find this defaultKey file&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; .foundry/keystores/
&lt;span class="c"&gt;# use the defaultKey&lt;/span&gt;
forge script script/DeployFundMe.s.so l:DeployFundMe –-account defaultKey &lt;span class="nt"&gt;--sender&lt;/span&gt; 0xf39fd6e51aad88f6f4cебab8827279cfffb92266
&lt;span class="c"&gt;# delete bash history &lt;/span&gt;
&lt;span class="nb"&gt;history&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; .bash_history
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Private key update, use cast provide by foundry.&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;I am looking forward to driving into the study Foundry. It takes me a little time to repair some errors in first using Foundry CLI.&lt;br&gt;
  It's useful and important to learn a new and much safer way to hold and use the private key.&lt;/p&gt;



&lt;p&gt;&lt;a id="lesson-6-7"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  lesson 6-7
&lt;/h2&gt;
&lt;h3&gt;
  
  
  14 Feb:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;script&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SimpleStorage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;SimpleStorage&lt;/span&gt; &lt;span class="n"&gt;simpleStorage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SimpleStorage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;simpleStorage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge script script/DeploySimpleStorage.s.sol &lt;span class="nt"&gt;--private-key&lt;/span&gt; &amp;lt;PRIVATE_KEY&amp;gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; &amp;lt;ALCHEMY_URL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;create a script to deploy.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;to-base&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cast &lt;span class="nt"&gt;--to-base&lt;/span&gt; 0x714c2 dec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Converts a number of one base to another [aliases: --to-base, --to-radix, to-radix, tr, 2r]&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;cast send &amp;amp; call&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cast send 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 &lt;span class="s2"&gt;"store(uint256)"&lt;/span&gt; 123 &lt;span class="nt"&gt;--rpc-url&lt;/span&gt;  &lt;span class="nt"&gt;--private-key&lt;/span&gt; 

cast call 0xcf7ed3acca5a467e9e704c703e8d87f634fbofc9 &lt;span class="s2"&gt;"retrieve()"&lt;/span&gt;
0x000000000000000000000000000000000000000000000000000000000000007

cast &lt;span class="nt"&gt;--to-base&lt;/span&gt; 0x000000000000000000000000000000000000000000000000000000000000007b dec
123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;forge fmt&lt;/em&gt;&lt;br&gt;
use forge fmt to format the code.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Transaction types&lt;/em&gt;&lt;br&gt;
there are several different types of transactions&lt;br&gt;
Transaction types：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Legacy: 0×0&lt;/li&gt;
&lt;li&gt;ΕIP-2930: 0×1&lt;/li&gt;
&lt;li&gt;ΕIP-1559: 0×2&lt;/li&gt;
&lt;li&gt;ΕIP-712: 0×71 // 113&lt;/li&gt;
&lt;li&gt;Priority: Oxff
add the-- Legacy flag it'll send it as a type zero transaction, if don't have the-- Legacy you're probably working with a type two.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;install lib&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge &lt;span class="nb"&gt;install &lt;/span&gt;smartcontractkit/chainlink-brownie-contracts &lt;span class="nt"&gt;--no-commit&lt;/span&gt;
remappings &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'@chainlink/contracts/=lib/chainlink-brownie-contracts/contracts/'&lt;/span&gt;,
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;owner == sender?&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;FundMeTest&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FundMe&lt;/span&gt; &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//us -&amp;gt; FundMeTest -&amp;gt; FundMe&lt;/span&gt;
    &lt;span class="n"&gt;fundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;testOwnerIsMsgSender&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// assertEq(fundMe.i_owner(), msg.sender)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;assertEq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i_owner&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;us -&amp;gt; FundMeTest -&amp;gt; FundMe:&lt;br&gt;
message sender is whoever's calling the fundme test.&lt;br&gt;
Actually we deploy the FundMeTest, then FundMeTest deploy the fundMe, so we should be checking to see if fundmetest is the owner.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are two way to complete the test correctly:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;use Deploy.s.sol to deploy
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;DeployFundMe&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"../script/DeployFundMe.s.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;FundMeTest&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FundMe&lt;/span&gt; &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;DeployFundMe&lt;/span&gt; &lt;span class="n"&gt;depoyFundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DeployFundMe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
        &lt;span class="n"&gt;fundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deployFundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When we use the run() function in the DeployFundMe.s.sol into FundMeTest to setup, owner will equal sender correctly.(because DeployFundMe.run() is called directly by us)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Values of address(this) and address(msg.sender) when testOwnerIsMsgSender() is run:&lt;/li&gt;
&lt;li&gt;this: FundMeTest Address of the contract&lt;/li&gt;
&lt;li&gt;msg.sender: us (Test account assigned by foundry)&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Deploy as the deployer
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;deployer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeAddr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"deployer"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Simulate a deployer address&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Deploy as the deployer&lt;/span&gt;
    &lt;span class="n"&gt;fundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopPrank&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;ourToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BOB_STARTING_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;testOwnerIsMsgSender&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;assertEq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;i_owner&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;🔹.&lt;em&gt;only test one&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; testone 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;only test the function testone.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;work with addresses onlink&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; testPriceFeedVersionIsAccurate &lt;span class="nt"&gt;-vvv&lt;/span&gt; &lt;span class="nt"&gt;--fork-url&lt;/span&gt; 
&lt;span class="nv"&gt;$SEPOLIA_RPC_UR&lt;/span&gt;
forge coverage &lt;span class="nt"&gt;--fork-url&lt;/span&gt; &lt;span class="nv"&gt;$SEPOLIA_RPC_URL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when we use a fork URL we're going to simulate what's on that actual chain, it is a great way for us to easily test our contracts on a forked blockchain.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unit : Testing a specific part of our code(only test FundMe.sol)&lt;/li&gt;
&lt;li&gt;Integration : Testing how our code works with other parts of our code(test combined FundMe.sol with deployFundMe.s.sol)&lt;/li&gt;
&lt;li&gt;Forked : Testing our code on a simulated real environment&lt;/li&gt;
&lt;li&gt;Staging : Testing our code in a real environment that is not prod.this is the last step in your development journey.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🔹.&lt;em&gt;modular deployments&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;AggregatorV3Interface&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;s_priceFeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s_priceFeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AggregatorV3Interface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make our deployments more modular with addresses or external systems, we can do a refactoring that pass an address price feed as a Constructor.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Config contract&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;HelperConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// If we are on a local anvil, we deploy mocks&lt;/span&gt;
    &lt;span class="c1"&gt;// Otherwise, grab the existing address from the live network&lt;/span&gt;
    &lt;span class="n"&gt;NetworkConfig&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;activeNetworkConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;NetworkConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ETH/USD price feed address&lt;/span&gt;
    &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chainid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;11155111&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;activeNetworkConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getSepoliaEthConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;activeNetworkConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getAnvilEthConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getSepoliaEthConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NetworkConfig&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Price feed address&lt;/span&gt;
        &lt;span class="n"&gt;NetworkConfig&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;sepoliaConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NetworkConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="nl"&gt;priceFeed:&lt;/span&gt; &lt;span class="mh"&gt;0x694AA1769357215DE4FAC081bf1f309aDC325306&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sepoliaConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAnvilEthConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NetworkConfig&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Price feed address&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This is a strategy we can work with different chains.&lt;/li&gt;
&lt;li&gt;Why use a struct instead of Assign a value to activeNetworkConfig directly?
Because Solidity contracts may constantly expand, Use struct for better scalability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;Before startBroadcast&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;DeployFundMe&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Script&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FundMe&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Before startBroadcast -&amp;gt; Not a "real" tx&lt;/span&gt;
        &lt;span class="n"&gt;HelperConfig&lt;/span&gt; &lt;span class="n"&gt;helperConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;HelperConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;ethUsdPriceFeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;helperConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activeNetworkConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// After startBroadcast -&amp;gt; Real tx!&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;FundMe&lt;/span&gt; &lt;span class="n"&gt;fundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;FundMe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ethUsdPriceFeed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we want to write a contract to implement some configuration functions, we can new and invoke it before startBroadcast.&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;At noon, I spent some time installing WSL on my Windows 10. Fortunately, the installation was successful. &lt;br&gt;
Today, I learned the basic test of foundry and learned about Script,test and config contracts.&lt;/p&gt;


&lt;h2&gt;
  
  
  lesson 7
&lt;/h2&gt;
&lt;h3&gt;
  
  
  15 Feb:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;mock&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAnvilEthConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NetworkConfig&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;uint8&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;DECIMALS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;int256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;INITIAL_PRICE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2000e8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="c1"&gt;// Check to see if we set an active network config&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localNetworkConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;priceFeed&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;localNetworkConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Price feed address&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;MockV3Aggregator&lt;/span&gt; &lt;span class="n"&gt;mockPriceFeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MockV3Aggregator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DECIMALS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;INITIAL_PRICE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="n"&gt;localNetworkConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NetworkConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mockPriceFeed&lt;/span&gt;&lt;span class="p"&gt;)});&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;localNetworkConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;mkdir -p test/mock &amp;amp;&amp;amp; touch test/mock/MockV3Aggregator.sol, then new MockV3Aggregator at HelperConfig.s.sol to deploy a mock contract to have our own fake price feed on Anvil.&lt;br&gt;
mock much faster than fork, we didn't have to make it any API calls.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;vm.expectRevert&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;testFundFailsWithoutEnoughETH&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expectRevert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fund&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// send 0 eth&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next line should revert.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;private&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;s_addressToAmountFunded&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getAddressToAmountFunded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;fundingAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;s_addressToAmountFunded&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fundingAddress&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;private variables are more &lt;strong&gt;gas efficient&lt;/strong&gt; so we just want to default them to private and then only make public or external view function (getter) as we need.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;makeAddr &amp;amp; deal&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;FundMe&lt;/span&gt; &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;USER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;makeAddr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;SEND_VALUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="n"&gt;ether&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;STARTING_BALANCE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="n"&gt;ether&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;DeployFundMe&lt;/span&gt; &lt;span class="n"&gt;deployFundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DeployFundMe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;fundMe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deployFundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;STARTING_BALANCE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;makeAddr(from forge-std)
Creates an address derived from the provided name.&lt;/li&gt;
&lt;li&gt;vm.deal
Sets the balance of an address who to newBalance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;vm.prank&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;testFundUpdatesFundedDataStructure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;prank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//The next TX will be sent by USER fundMe. &lt;/span&gt;
        &lt;span class="n"&gt;fund&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SEND_VALUE&lt;/span&gt;&lt;span class="p"&gt;}();&lt;/span&gt; 
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amountFunded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getAddressToAmountFunded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
        &lt;span class="n"&gt;assertEq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amountFunded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SEND_VALUE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;getOwner&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopPrank&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;knowing who is doing what can be a little bit confusing especially in our tests, so in our test we want to be very explicit with who's sending what transactions and that's where we can use another foundary cheatcode called prank.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;test with modifier&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="nf"&gt;funded&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fund&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SEND_VALUE&lt;/span&gt;&lt;span class="p"&gt;}();&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;testOnlyOwnerCanWithdraw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;funded&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;USER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expectRevert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
    &lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you call payable (ETH payable) function, ETH can be appended using the {value: amount} syntax.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;test pattern&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arrange: 
first I'm going to arrange the test I'm&lt;/li&gt;
&lt;li&gt;Act: 
then I'm going to do the action I actually want to test&lt;/li&gt;
&lt;li&gt;Assert: 
then I'm going to assert the test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;uint160&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint160&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;uint160&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;startingFunderIndex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As of Solidity v0.8, you can no longer cast explicitly from address to uint256.&lt;br&gt;&lt;br&gt;
The reason for this is a uint160 has the same amount of bytes essentially as an address. So if you want to use numbers to generate addresses those numbers have to be a uint160.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;hoax&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vm.prank new address&lt;/span&gt;
&lt;span class="c1"&gt;// vm.deal new address&lt;/span&gt;
&lt;span class="n"&gt;hoax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;SEND_VALUE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sets up a prank from an address that has some ether. It does both prank and deal combined.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;gas-snapshot&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge snapshot &lt;span class="nt"&gt;-m&lt;/span&gt; testWithdrawFromMultipleFunders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's going to create this file called gas snapshot for us and tell us exactly how much gas this single test costs.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;vm.txGasPrice&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//Act &lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;GAS_PRICE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;gasStart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gasleft&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//1000&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txGasPrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GAS_PRICE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getowner&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;//c: 200&lt;/span&gt;
&lt;span class="n"&gt;fundMe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//should have spent gas?&lt;/span&gt;

&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;gasEnd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gasleft&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//800&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;gasUsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gasStart&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;gasEnd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gasprice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gasUsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;when you're working with Anvil the gas price actually defaults to zero(whether forked or not).&lt;/li&gt;
&lt;li&gt;gas left function is a built-in function in solidity it tells you how much gas is left in your transaction call.&lt;/li&gt;
&lt;li&gt;tx. gas price is built-in to solidity which tells you the current gas price&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;Storage&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbvkhjnk9f0bj1bgad4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbvkhjnk9f0bj1bgad4l.png" alt="Image description" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;for array it does have a storage slot for the length, for mappings it does have a storage spot as well similar to array, but it's just blank intentionally so that solidity knows ah okay there is a mapping here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;cast&lt;/span&gt; &lt;span class="n"&gt;storage&lt;/span&gt; &lt;span class="n"&gt;ADDRESS&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;slot&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66agsumw1qwneb6bd4i6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66agsumw1qwneb6bd4i6.png" alt="Image description" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;integration tests&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;integration tests are when you test a lot of your interactions and combinations of systems.&lt;/li&gt;
&lt;li&gt;is going to be testing all of our deploy scripts and how all of our contracts interact with each other.&lt;/li&gt;
&lt;li&gt;At FundMeTest.s.sol we tested funding and withdrawing, but we didn't test funding and withdrawing using the methods that we're actually going to use to do that when we actually call funds and withdraws we're do it with Forge script.&lt;/li&gt;
&lt;li&gt;integration tests is going to have a programmatic way to do it with Forge script so that we can have a reproducible way to actually interact with fund and withdraw.it simulated real user interaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;get_most_recent_deployment&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;mostRecentlyDeployed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DevOpsTools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_most_recent_deployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"FundMe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chainid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;fundFundMe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mostRecentlyDeployed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Has this devops tool to get the most recent deployment that we can use to get the most recently deployed version of a contract, this way we don't have to pass the fundme contract address that we want to work with every single time.(because when we run “forge script”, function &lt;code&gt;run()&lt;/code&gt; is must implemented in our script).&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today, I learned a lot about foundry testing, such as mock and integration. Although Patrick's tutorial only watched 1 and a half hours of video, I felt that I learned so much today that I gave up watching the tutorial tonight. Instead, I will try to run what I learned today in my own vscode and finally pass all the tests.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-7-9"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 7-9
&lt;/h2&gt;

&lt;h3&gt;
  
  
  16 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;window.ethereum&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BrowserProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eth_requestAccounts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;withdrawButton&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please install MetaMask&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's this window.ethereum JavaScript object that these websites interact with to send transactions to our metamask. &lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;function selectors&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;cast&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt; &lt;span class="s"&gt;"fund()"&lt;/span&gt; 
&lt;span class="mh"&gt;0xb60d4288&lt;/span&gt;
&lt;span class="cp"&gt;# this is the function selector
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;solidity functions get transformed into this thing called a function selector， when calling this fund function is it converts it to its function selector&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Solidity Layout&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Layout of Contract:&lt;br&gt;
version&lt;br&gt;
imports&lt;br&gt;
errors&lt;br&gt;
interfaces, libraries, contracts&lt;br&gt;
Type declarations&lt;br&gt;
State variables&lt;br&gt;
Events&lt;br&gt;
Modifiers&lt;br&gt;
Functions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Layout of Functions:&lt;br&gt;
constructor&lt;br&gt;
receive function (if exists)&lt;br&gt;
fallback function (if exists)&lt;br&gt;
external&lt;br&gt;
public&lt;br&gt;
internal&lt;br&gt;
private&lt;br&gt;
view &amp;amp; pure functions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;custom error&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// require(msg. value &amp;gt;= i_entranceFee, "Not enough ETH sent!");&lt;/span&gt;
&lt;span class="c1"&gt;// 0.8.26 :&lt;/span&gt;
&lt;span class="c1"&gt;// require(msg. value &amp;gt;= i_entranceFee, SendMoreToEnterRaffle());&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;i_entranceFee&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;revert&lt;/span&gt; &lt;span class="n"&gt;Raffle_SendMoreToEnterRaffle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last is the most gas efficient out of all these methodologies.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;payable addrass&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;notPayableAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;payable&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;payableAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// send ETH to address and it's not payable, the transaction will fail&lt;/span&gt;
&lt;span class="c1"&gt;// notPayableAddress.transfer(1 ether);&lt;/span&gt;
&lt;span class="n"&gt;payable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notPayableAddress&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;ether&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which can receive ETH ?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;address   : no&lt;/li&gt;
&lt;li&gt;address payable   : yes&lt;/li&gt;
&lt;li&gt;contract（no receive or fallback) : no&lt;/li&gt;
&lt;li&gt;contract(have receive()) : yes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;event&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5esjd75ockwjur8muk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5esjd75ockwjur8muk1.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(Indexed Parameters = Topics) we can have up to three indexed parameters. Topics are searchable.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="n"&gt;storedNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;oldNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;newNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;addedNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;sender&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;emit&lt;/span&gt; &lt;span class="nf"&gt;storedNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;favoriteNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;favoriteNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;favoriteNumber&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;favoriteNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;whenever we update something in storage and this rule of thumb is going to always be emitting an event whenever we update a storage variable.
the two main reasons that work with events:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Makes migration easier : it can be very difficult to move all the storage to the new contract.&lt;/li&gt;
&lt;li&gt;Makes front end "indexing" easier.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🔹.&lt;em&gt;block.timestamp&lt;/em&gt;&lt;br&gt;
it's going to be the current approximate time of according to the blockchain.&lt;/p&gt;
&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today I reviewed the Foundry Fund Me code and uploaded it to GitHub, watched Patrick demonstrate metamask's interaction with the site, and pulled the code and tried it out myself. Finally, start learning Smart Contract Lottery.&lt;/p&gt;


&lt;h2&gt;
  
  
  lesson 9
&lt;/h2&gt;
&lt;h3&gt;
  
  
  17 Feb:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;verifiable Randomness function (vrf)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pickWinner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Check to see if enough time has passed&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;s_lastTimeStamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;i_interval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;revert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Fill in parameter&lt;/span&gt;
        &lt;span class="n"&gt;VRFV2PlusClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RandomWordsRequest&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VRFV2PlusClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RandomWordsRequest&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="nl"&gt;keyHash:&lt;/span&gt; &lt;span class="n"&gt;i_keyHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;subId:&lt;/span&gt; &lt;span class="n"&gt;i_subscriptionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;requestConfirmations:&lt;/span&gt; &lt;span class="n"&gt;REQUEST_CONFIRMATIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;callbackGasLimit:&lt;/span&gt; &lt;span class="n"&gt;i_callbackGasLimit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;numWords:&lt;/span&gt; &lt;span class="n"&gt;NUM_WORDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nl"&gt;extraArgs:&lt;/span&gt; &lt;span class="n"&gt;VRFV2PlusClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_argsToBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="c1"&gt;// Set nativePayment to true to pay for VRF requests with Sepolia ETH instead of LINK&lt;/span&gt;
                &lt;span class="n"&gt;VRFV2PlusClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExtraArgsV1&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;nativePayment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="c1"&gt;// Request Chainlink VRF Oracle.&lt;/span&gt;
        &lt;span class="c1"&gt;// The oracle submits random numbers and proofs to the Chainlink VRF Coordinator contract.&lt;/span&gt;
        &lt;span class="c1"&gt;// Chainlink VRF generates the unique identifier requestId for this request&lt;/span&gt;
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;requestId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s_vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requestRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// The Chainlink VRF Coordinator calls the rawFulfillRandomWords of your contract after the oracle returns the data.&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fulfillRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;randomWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fill in parameter.&lt;/li&gt;
&lt;li&gt;Request Chainlink VRF Oracle.&lt;/li&gt;
&lt;li&gt;The oracle submits random numbers and proofs to the Chainlink VRF Coordinator contract.&lt;/li&gt;
&lt;li&gt;Chainlink VRF generates the unique identifier requestId for this request&lt;/li&gt;
&lt;li&gt;The Chainlink VRF Coordinator calls the rawFulfillRandomWords of your contract after the oracle returns the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;safety design&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fulfillRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;randomWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;rawFulfillRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;randomWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s_vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;revert&lt;/span&gt; &lt;span class="n"&gt;OnlyCoordinatorCanFulfill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s_vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fulfillRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;randomWords&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;rawFulfillRandomWords ensure the separation of security checks and business logic.&lt;/li&gt;
&lt;li&gt;fulfillRandomWords are internal and cannot be called directly from the outside.Outsiders can only call rawFulfillRandomWords that have been checked for security.&lt;/li&gt;
&lt;li&gt;Why not just allow subcontracts to implement rawFulfillRandomWords directly? The subcontract may forget or intentionally delete msg.sender validation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;inherit Constructor&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// contract VRFConsumerBaseV2Plus:&lt;/span&gt;
  &lt;span class="n"&gt;IVRFCoordinatorV2Plus&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;s_vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;_vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ConfirmedOwner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_vrfCoordinator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;revert&lt;/span&gt; &lt;span class="n"&gt;ZeroAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;s_vrfCoordinator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IVRFCoordinatorV2Plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// contract Raffle &lt;/span&gt;
&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;Raffle&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;VRFConsumerBaseV2Plus&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;entranceFee&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;VRFConsumerBaseV2Plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i_entranceFee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entranceFee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;i_interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;s_lastTimeStamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;requestId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s_vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;requestRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if we we use the Constructor of the inherited contract then we need to add that inherited contract's Constructor. We're inheriting so we get access to these State variables too.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;abstract contract&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fulfillRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;randomWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// implement:&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fulfillRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* requestId */&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;randomWords&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;contract abstract contracts can have both undefined functions [virtual] and defined functions. inherit an abstract contract must Implement functions that it undefined [override].&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Enum&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;RaffleState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;OPEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// 0&lt;/span&gt;
        &lt;span class="n"&gt;CALCULATING&lt;/span&gt;    &lt;span class="c1"&gt;// 1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;s_raffleState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RaffleState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OPEN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s_raffleState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;keep track of the raffle and figure out are we in the middle of calculating the winner.&lt;/li&gt;
&lt;li&gt;each one of these parameters inside of enum get mapped to a un 256.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹🔹🔹.&lt;em&gt;CEI Patten&lt;/em&gt;&lt;br&gt;&lt;br&gt;
keep checks effects interactions in mind that will help you just be safer by default (defend against re-entrancy attacks).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checks (conditionals)&lt;/li&gt;
&lt;li&gt;Effect (Internal Contract State and emit Event)&lt;/li&gt;
&lt;li&gt;Interactions (External Contract Interactions) &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🔹.&lt;em&gt;calldata&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;calldata is part of the EVM transaction calldata and is stored directly in the input data of the transaction call, not in memory within Solidity code.&lt;/li&gt;
&lt;li&gt;The calldata variable is immutable and is used only as an argument to external functions, in order to save gas and avoid copying data to memory.&lt;/li&gt;
&lt;li&gt;internal functions cannot use calldata, only memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;pure&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;hashData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodePacked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  &lt;span class="c1"&gt;// Calculates the hash without modifying the contract state&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;pure is suitable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✔ Pure mathematical operations&lt;/li&gt;
&lt;li&gt;✔ Handle strings, arrays, and do not access contract storage&lt;/li&gt;
&lt;li&gt;✔ Calculate the hash value&lt;/li&gt;
&lt;li&gt;✔ Check input data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;cannot be used pure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Access state variables&lt;/li&gt;
&lt;li&gt;❌ Modifies the stored variable&lt;/li&gt;
&lt;li&gt;❌ Access global variables such as msg.sender, block.timestamp&lt;/li&gt;
&lt;li&gt;❌ calls a function of view or non-pure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;when use memory&amp;amp;calldata&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The base type uint256 is used as the argument and return value and does not require a storage location&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Passing the string argument must specify either memory or calldata&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodePacked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"!"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when require a storage location in parameter and return？&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;uint256、bool、address❌ &lt;/li&gt;
&lt;li&gt;string、struct、array   ✔&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;Mock &amp;amp; Fork&lt;/em&gt;&lt;br&gt;
 Whether VRF contract exists? Mock is needed? VRF predictor responds?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local Anvil :   ❌ ✔ ❌&lt;/li&gt;
&lt;li&gt;Forked Sepolia : ✔ ✔ ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On Forked Sepolia, even with a real VRF contract, the oracle won't respond to Fork network requests, so you'll still need Mock.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Test Event&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;testEnteringRaffleEmitsEvent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PLAYER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Act&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expectEmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raffle&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="n"&gt;emit&lt;/span&gt; &lt;span class="nf"&gt;RaffleEntered&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PLAYER&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="c1"&gt;// Assert&lt;/span&gt;
    &lt;span class="n"&gt;raffle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enterRaffle&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entranceFee&lt;/span&gt;&lt;span class="p"&gt;}();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;It's the first index parameter, so we are going to say true, there are no additional index parameters (up to 3), and there are also no non-indexed parameters, so we're going to say false, raffle address is actually going to be emitting.&lt;/li&gt;
&lt;li&gt;We have to copy paste our events into the top of our test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;warp &amp;amp; roll&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// set time passed&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;warp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// set the blocks increased.&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;roll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time has passed and the blocks have actually increased.&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today I learned vrf, knowing how to get a random number and implemented it basically. Then make a HelperConfig.s.sol to set config for different networks. Starting in the evening, studying for the Raffle Test. I had the pleasure of reviewing a lot of solidity's basic syntax while implementing Raffle.&lt;/p&gt;




&lt;h2&gt;
  
  
  lesson 9
&lt;/h2&gt;

&lt;h3&gt;
  
  
  18 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;function selector databases&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qs7a6yxxd7gtf09c9rk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qs7a6yxxd7gtf09c9rk.png" alt="Image description" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;function signature or function selector&lt;br&gt;
&lt;a href="https://dev.tourl"&gt;openchain.xyz/signatu res&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;import&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// deploy VRFCoordinatorV2_5Mock contract&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt; &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MOCK_BASE_FEE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MOCK_GAS_PRICE_LINK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MOCK_WEI_PER_UINT_LINK&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// invoke VRFCoordinatorV2_5Mock function in another contract&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;createSubscription&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;"import" only imports the ABI of the contract.&lt;/li&gt;
&lt;li&gt;The cast VRFCoordinatorV2_5Mock(vrfCoordinator) simply tells the compiler that the address matches the ABI, Solidity will call the function on chain use the ABI.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;Create Subscription&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mock VRFCoordinatorV2_5Mock.sol form chainlink.&lt;/li&gt;
&lt;li&gt;Create a helperconfig.s.sol to configure NetworkConfig for sepolia and deploy a mock VRF contract for local chain.&lt;/li&gt;
&lt;li&gt;Create an interactions.s.sol to implement the interaction logic speciality.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;subId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createSubscription&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;new CreateSubscription in DeployRaffle.s.sol:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// create subscription&lt;/span&gt;
    &lt;span class="n"&gt;CreateSubscription&lt;/span&gt; &lt;span class="n"&gt;createSubscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;CreateSubscription&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;createSubscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;createSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;Fund Subscription&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mock LinkToken.sol form chainlink.&lt;/li&gt;
&lt;li&gt;import ERC20.sol:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge &lt;span class="nb"&gt;install &lt;/span&gt;transmissions11/solmate@v6 &lt;span class="nt"&gt;--no-commit&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;add remappings =['@solmate=lib/solmate/src/'] in foundry.toml.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ERC20&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"@solmate/tokens/ERC20.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;add mint function:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;deploy LinkToken in HelperConfig.s.sol, and use it on Anvil NetworkConfig.&lt;/li&gt;
&lt;li&gt;create contract FundSubscription in interactions.s.sol and write a fundSubscription to fund for subscriptionId:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fundSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;linkToken&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chainid&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;LOCAL_CHAIN_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="c1"&gt;// this fundSubscription is provide by VRFCoordinatorV2_5Mock.sol specially&lt;/span&gt;
            &lt;span class="n"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;fundSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;FUND_AMOUNT&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;LinkToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linkToken&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;transferAndCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;FUND_AMOUNT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;new FundSubscription and fund subscriptionId in DeployRaffle.s.sol
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//  Found it!&lt;/span&gt;
&lt;span class="n"&gt;FundSubscription&lt;/span&gt; &lt;span class="n"&gt;fundSubscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FundSubscription&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;fundSubscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fundSubscription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;use FundSubscription to fund on sepolia:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge script script/Interactions.s.sol:FundSubscription &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://eth-sepolia.g.alchemy.com/v2/xxx &lt;span class="nt"&gt;--private-key&lt;/span&gt; xxxx &lt;span class="nt"&gt;--broadcast&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;Add Consumner&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;forge install Cyfrin/foundry-devops --no-commit
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;mostRecentlyDeployed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DevOpsTools&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;get_most_recent_deployment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Raffle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;chainid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create contract AddConsumer in interactions.s.sol and write an addConsumer to add the most recent deployment contract Raffle for the Consumer.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;contractToAddToVrf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;subId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Adding consumer contract: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contractToAddToVrf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"To vrfCoordinator: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"On ChainId: "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chainid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;addConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contractToAddToVrf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;new AddConsumer in DeployRaffle.s.sol:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;AddConsumer&lt;/span&gt; &lt;span class="n"&gt;addConsumer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AddConsumer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;//have broadcast in AddConsumer&lt;/span&gt;
&lt;span class="n"&gt;addConsumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raffle&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;subscriptionId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;coverage report&lt;/em&gt;----t=65086&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;forge&lt;/span&gt; &lt;span class="n"&gt;coverage&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;coverage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;recordLogs&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recordLogs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;raffle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;performUpkeep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getRecordedLogs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;requestId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;whatever events whatever logs are emitted by this performupkeep&lt;br&gt;
function, keep track of those and stick them into an array.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;fuzz testing&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[fuzz]
runs = 1000
# testFulfillrandomWordsCanOnlyBeCalledAfterPerformUpkeep(uint256) (runs: 1000)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Test try to break the code.&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today I followed Patrick done the Subscription create and found, add Consumner. Found subscription on sepolia. Do some tests to the raffle contract.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-9-10"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 9-10
&lt;/h2&gt;

&lt;h3&gt;
  
  
  19 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;About test fulfillRandomWords&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vrfCoordinator is the deploy address of vrfCoordinatorV2_5Mock in HelperConfig.s.sol&lt;/span&gt;
&lt;span class="n"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;fulfillRandomWords&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raffle&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Why can this invoke the fulfillRandomWords at Raffle?
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// VRFCoordinatorV2_5Mock.sol :&lt;/span&gt;
   &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;callReq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodeWithSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rawFulfillRandomWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_requestId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_words&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;s_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reentrancyLock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// solhint-disable-next-line avoid-low-level-calls, no-unused-vars&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_consumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;gas&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;callbackGasLimit&lt;/span&gt;&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;callReq&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VRFCoordinatorV2_5Mock is just an intermediary that triggers Raffle's fulfillRandomWords method with a low-level call&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When testing the fulfillRandomWords, why don't invoke fulfillRandomWords at Raffle directly ?&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;fulfillRandomWords is internal.&lt;/li&gt;
&lt;li&gt;fulfillRandomWords is the callback function, which must be called by &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🔹.&lt;em&gt;default caller address&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib &amp;gt; forge-std &amp;gt; src &amp;gt; Base.sol&lt;/span&gt;
&lt;span class="n"&gt;abstract&lt;/span&gt; &lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;CommonBase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;//Default address for tx. origin and msg. sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_SENDER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint160&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"foundry default caller"&lt;/span&gt;&lt;span class="p"&gt;))));&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;whenever Foundry needs to use some type of address to send some stuff this is the address that it's going to use.So in helperconfig we can set the local network default account to being this.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Fork tests&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// fulfillRandomWords is only can be called by vrf, so at fork network we skip it&lt;/span&gt;
    &lt;span class="n"&gt;modifier&lt;/span&gt; &lt;span class="nf"&gt;skipFork&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chainid&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;31337&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual chain link coordinator have access controls and only let the chain link nodes call fulfillrandomwords.&lt;br&gt;
we're going to skip those two that don't make sense for us to to Fork.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;startBroadcast(address)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;who&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;privatekey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Use the address to broadcast things.&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startBroadcast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Raffle&lt;/span&gt; &lt;span class="n"&gt;raffle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Raffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopBroadcast&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;stages, scope and type of tests&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unit&lt;/li&gt;
&lt;li&gt;integrations&lt;/li&gt;
&lt;li&gt;forked&lt;/li&gt;
&lt;li&gt;&lt;p&gt;staging  &amp;lt;- run tests on a mainnet or testnet&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fuzzing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stateful fuzz&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;stateless fuzz&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;formal verification  &amp;lt;- turn your code into mathematical proofs&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;verify-contract&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;forge&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="mh"&gt;0xA7Deda6D9a52A43E39C655453C2F7b3a203Da671&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Raffle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;sol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Raffle&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;etherscan&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;ETHERSCAN_API_KEY&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;rpc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;SEPOLIA_RPC_URL&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;standard&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if for some reason your code doesn't automatically update your code doesn't automatically verify this is how to do. --&amp;gt; [t=69099]&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;ERC20Token&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ERC20&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s"&gt;"@openzeppelin/contracts/token/ERC20/ERC20.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;OurToken&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ERC20&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;initialSupply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ERC20&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OurToken"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;initialSupply&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;transferFrom&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;_spendAllowance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;spender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Gets the amount of spender currently authorized by the owner&lt;/span&gt;
    &lt;span class="c1"&gt;// allowance is record by mapping(address =&amp;gt; mapping(address =&amp;gt; uint256)) _allowances;&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;currentAllowance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;allowance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
    &lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentAllowance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ERC20: insufficient allowance"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;unchecked&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;currentAllowance&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Renewal of authorization&lt;/span&gt;
            &lt;span class="n"&gt;_approve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currentAllowance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;transferFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_spendAllowance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Consumption authorization&lt;/span&gt;
    &lt;span class="n"&gt;_transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;transferFrom() use _spendAllowance() to check and consume the authorized amount, use _transfer() to do transfer.&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Finished a learning raffle course, passed all the tests and deployed to sepolia, pushed to GitHub. learned Foundry ERC20s, did some tests with the help of AI.Drive into Advanced Foundry.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-11"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 11
&lt;/h2&gt;

&lt;h3&gt;
  
  
  20 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;IPFS&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IPFS drastically different than a blockchain is they din't have execution it's just decentralized storage.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unlike a blockchain where every single node in a blockchain is going to have a copy of the entire blockchain ipfs nodes get to optionally choose which data they want to pin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pinata is an IPFS third-party hosting service, we can upload files to IPFS without having to run IPFS nodes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filecoin and arweave are two decentralized storage platforms that we could alternatively use instead of ipfs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;compare stirngs&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;expectedName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Dogie"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;actualName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;basicNft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;//assert(expectedName == actualName); assert(keccak256(abi.encodePacked(expectedName)) == keccak256(abi.encodePacked(actualName));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare the two of them we would just compare the hashes instead of looping through the array.&lt;br&gt;
we can convert our strings to bytes and convert the bytes to a byes 32 and we just compare the hashes of both of those.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;SVG NFT&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store NFT in Scalable Vector Graphics (SVG) format directly in a smart contract, never lose.&lt;/li&gt;
&lt;li&gt;NFT has the ability to change dynamically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;differences between a unit test and an integration test&lt;/em&gt;--&amp;gt;[t=78423]&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unit : Testing a specific part of a contract.(only test FundMe.sol)&lt;/li&gt;
&lt;li&gt;Integration : Testing how our contracts works with each other.(test combined FundMe.sol with deployFundMe.s.sol)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Learned ERC721, IPFS storage for NFT (test on sepolia), SVG format NFT for full on-chain storage (test on anvil, sepolia is insufficient funds for gas).spent some time on unit testing.&lt;/p&gt;


&lt;h2&gt;
  
  
  lesson 11
&lt;/h2&gt;
&lt;h3&gt;
  
  
  21 Feb:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;encode&lt;/em&gt;-&amp;gt;[t=79079]&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;abi.encode("string")&lt;/li&gt;
&lt;li&gt;bi.encodePacked("string")&lt;/li&gt;
&lt;li&gt;bytes("string")&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;abi.encodePacked() it's the encode function but it compresses stuff if we wanted to encode some string but we wanted to save space and we didn't need the perfect low-level binary of it.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;EncodePacked and bytes get the same result.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dncode:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;abi.decode(encodeString(), (string))&lt;/li&gt;
&lt;li&gt;string(EncodePacked()&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🔹.&lt;em&gt;call&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example Function Selector:&lt;/span&gt;
&lt;span class="mh"&gt;0xa9059cbb&lt;/span&gt; 
&lt;span class="c1"&gt;// Example Function Signature:&lt;/span&gt;
&lt;span class="s"&gt;"transfer(address, uint256)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The Function Selector for each function is the hash of its first 4 bytes.
bytes4(keccak256(bytes("transfer(address,uint256)")));
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// use selector and calldata to call a function&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callTransferFunctionDirectly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;someAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;returnData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="c1"&gt;// getDataToCallTransfer(someAddress, amount);&lt;/span&gt;
            &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodeWithSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getSelectorOne&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;someAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;returnData&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;call calls only the methods of the target contract based on the ABI encoding (Function Selector + Arguments Encoding). &lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;stable coin&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classification of stable coin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Algorithmic stable coins use some sort of autonomous permissionless code to Mint and burn tokens whereas a govern stable coin have some human interaction that mints and burns the coins and keeps them stable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Classification of collateral:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;exogenous collateral is collateral that originates from outside the protocol &lt;/li&gt;
&lt;li&gt;endogenous collateral originates from inside the protocol &lt;/li&gt;
&lt;li&gt;one of the easier ways to Define what type of collateral protocol is using is to ask this question if the stable coin fails does the underlying collateral also fail if yes it's endogenous if no it's exogenous. exogenously collateralized stable coins are typically over collateralized.&lt;/li&gt;
&lt;li&gt;was the collateral created with the sole purpose of being collateral or does the protocol own the issuance of the underlying collateral if the answer is yes to either one of those then it's endogenous collateral&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;RAI:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;so protocols like RAI have come a long way to do some type of hybrid between endogenous and exogenously collateralized stable coin.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;who is minting these stable coins and pay Stability Fee?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;people who want to own more eth. (maximize your position)&lt;br&gt;
put eth into one of these stable coin protocols minted stable coin and then sell the stable coin for more eth.&lt;/p&gt;
&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today I learned abi.encode,call function with Selector, and have a basic understanding of stablecoins.Start to learn the building of stablecoins project.&lt;/p&gt;



&lt;p&gt;&lt;a id="lesson-12"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  lesson 12
&lt;/h2&gt;
&lt;h3&gt;
  
  
  22 Feb:
&lt;/h3&gt;
&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;address cast&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ tokenCollateralAddress inherit IERC20&lt;/span&gt;
&lt;span class="n"&gt;IERC20&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenCollateralAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="c1"&gt;// ❌ tokenCollateralAddress inherit ERC20, But the contract  of tokenCollateralAddress itself is not ERC20&lt;/span&gt;
&lt;span class="n"&gt;ERC20&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenCollateralAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   
&lt;span class="c1"&gt;// ✅ The contract  of vrfCoordinator itself is VRFCoordinatorV2_5Mock, vrfCoordinator address points to a VRFCoordinatorV2_5Mock contract that has been deployed&lt;/span&gt;
&lt;span class="n"&gt;VRFCoordinatorV2_5Mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vrfCoordinator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Convert the address to a contract interface.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Reentrant&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Not enough balance"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="c1"&gt;// ⚠️ A reentrant attack may occur here&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Transfer failed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// contract Attacker, call withdraw again when ETH is received.&lt;/span&gt;
    &lt;span class="n"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;payable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;ether&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// use ReentrancyGuard&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"@openzeppelin/contracts/security/ReentrancyGuard.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;SecureContract&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ReentrancyGuard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;nonReentrant&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;nonReentrant is required for any function that involves an external contract interaction and may cause a change in funds.&lt;/li&gt;
&lt;li&gt;If the contract changes its state before invoking the external contract, it can effectively prevent reentrant attacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;burnDsc&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;_burnDsc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amountDscToBurn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;onBehalfOf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;dscFrom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;s_DSCMinted&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;onBehalfOf&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;amountDscToBurn&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// user approve this,this invoke the transferFrom of dsc through ABI to transfer token to this&lt;/span&gt;
    &lt;span class="c1"&gt;// because only the token holder can call the burn function&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i_dsc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transferFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dscFrom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;amountDscToBurn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// This conditional is hypothetically unreachable&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;revert&lt;/span&gt; &lt;span class="n"&gt;DSCEngine__TransferFailed&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// now the token owner is this ,this can call the burn&lt;/span&gt;
    &lt;span class="n"&gt;i_dsc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;burn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amountDscToBurn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;user approve token to DSCEngine, DSCEngine invoke transferFrom to transfer token to itself, it own the token and can call the burn.&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today I basically understand some of the implementation logic of DSCEngine, such as depositCollateral, MintDsc, redeemCollateral, burnDsc, learned how to implement them.&lt;/p&gt;




&lt;h2&gt;
  
  
  lesson 12
&lt;/h2&gt;

&lt;h3&gt;
  
  
  23 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;Fuzz Testing&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Foundry Fuzzing = Stateless fuzzing&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Foundry Invariant = Stateful fuzzing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fuzz Testing: supply random data to your system in an attempt to break it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Invariant: Property of our system that should always hold. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stateless fuzzing &amp;amp; statefull fuzzing: &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;stateful fuzzing is where the final state of your previous fuzz run is the starting state of the next fuzz run.&lt;/li&gt;
&lt;li&gt;Statefull fuzzing is when you give random data and random function calls to a system to see if it breaks.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🔹.&lt;em&gt;Open Invariant Testing&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;fail_on_revert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;OpenInvariantsTest&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;StdInvariant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;deployer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DeployDSC&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dsc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dsce&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deployer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wbtc&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activeNetworkConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;targetContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dsce&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;invariant_protocolMustHaveMoreValueThanTotalSupply&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At competitive audit a lot of times will have revert on false, so you can write up invarant test quickly with mini handlers.&lt;br&gt;
But the open invarant have major flaw where it's probably making a bunch of silly calls, maybe it's just trying to deposit collateral but it keeps using random collateral addresses that don't make any sense. So this is great for very small contracts.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Handler&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;tHandler&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Test&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DSCEngine&lt;/span&gt; &lt;span class="n"&gt;_dscEngine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DecentralizedStableCoin&lt;/span&gt; &lt;span class="n"&gt;_dsc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;depositCollateral&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;collateralSeed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amountCollateral&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ERC20Mock&lt;/span&gt; &lt;span class="n"&gt;collateral&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_getCollateralFromSeed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collateralSeed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;amountCollateral&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amountCollateral&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MAX_DEPOSIT_SIZE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;collateral&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amountCollateral&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;collateral&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;approve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dsce&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;amountCollateral&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;dsce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;depositCollateral&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collateral&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;amountCollateral&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopPrank&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;/// Helper Functions&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_getCollateralFromSeed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;collateralSeed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERC20Mock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collateralSeed&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;weth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wbtc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the downside of always aiming for revert to be ture, is that if you make your Handler too specific, maybe you'll actually narrow it down and remove edge cases that would break the system that are valid right.&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today, I finished learning the content of the DSCEngine contract, this contract is the most complex that I have learned at present, I just understand the code logic, and I am not familiar with it. Trying to write a few unit tests that afternoon didn't go well either, I will slowly write the rest in the future. Start learn Advanced Testing in the evening.&lt;/p&gt;




&lt;h2&gt;
  
  
  lesson 12
&lt;/h2&gt;

&lt;h3&gt;
  
  
  24 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;ghost variable&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;timesMintIsCalled&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// address[] public usersWithCollateralDeposited;&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;mintDsc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="cm"&gt;/*, uint256 addressSeed*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// here's the problem, you have to restrict the sender to who has deposited collateral.&lt;/span&gt;
    &lt;span class="c1"&gt;// address sender = usersWithCollateralDeposited[addressSeed % usersWithCollateralDeposited.length];&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;totalDscMinted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;collateralValueInUsd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dsce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getAccountInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;int256&lt;/span&gt; &lt;span class="n"&gt;maxDscToMint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collateralValueInUsd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;int256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;totalDscMinted&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxDscToMint&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxDscToMint&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;dsce&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mintDsc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopPrank&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;timesMintIsCalled&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;it must be because one of these returns is hitting and it's not finishing this call.&lt;/li&gt;
&lt;li&gt;we can use called ghost variable to track this.&lt;/li&gt;
&lt;li&gt;we could keep moving this up to figure out where it's actually being called and to continue to debug this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;ContinueOnRevert&lt;/em&gt;&lt;br&gt;
ContinueOnRevert is going to be the quicker looser test.&lt;br&gt;
FailOnRevert is going to make sure that every single transaction that you run your invariant test is going to pass.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;use Oracles in a safer way&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt; &lt;span class="n"&gt;OracleLib&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;OracleLib__StalePrice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;staleCheckLatestRoundData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AggregatorV3Interface&lt;/span&gt; &lt;span class="n"&gt;chainlinkFeed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt;
        &lt;span class="n"&gt;view&lt;/span&gt;
        &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;int256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{...}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;OracleLib&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;AggregatorV3Interface&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;We should add some checks in our code to make sure that if oracle price feed breaks or if something in here breaks our system isn't broken.&lt;/li&gt;
&lt;li&gt;We want to check to make sure that these prices aren't stale(whether updating every 3600 seconds).&lt;/li&gt;
&lt;li&gt;If a price is stale, the function will revert, and render the DSCEngine unusable.&lt;/li&gt;
&lt;li&gt;We'll have this stale price check be on AggregatorV3Interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Completed the stablecoin course, but lacked practice. In this process, I not only learned how to implement the contract of stablecoin, but more importantly, I learned a lot of testing skills, which need to be practiced in the future to master.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-13"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 13
&lt;/h2&gt;

&lt;h3&gt;
  
  
  25 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;Merkle Proof&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="s"&gt;"inputs"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;"0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"25000000000000000000"&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="s"&gt;"proof"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s"&gt;"0x0fd7c981d39bece61f7499702bf59b3114a90e66b51ba2c53abdf7b62986c00a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"0xe5ebd1e1b5a5478a944ecab36a9a954ac3b6b8216875f6524caa7a1d87096576"&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"0xaa5d581231e596618465a56aa0f5870ba6e20785fe436d5bfb82b08662ccc7c4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="s"&gt;"leaf"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"0xd1445c931158119b00449ffcac3c947d028c0c359c34a6646d95962b3b55c6ad"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The data in proof is the sibling of the parent node and is used to reproduce the hash path. root is the same.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Merkel trees is a cryptographic data structure using hashes.&lt;/li&gt;
&lt;li&gt;Merkel proofs allow us to prove that some piece of data that we want is in fact in a group of data.(to prove you're part of a group)&lt;/li&gt;
&lt;li&gt;often used in airdrops and also verifying State changes in smart contracts and in rollups.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;SafeERC20&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;SafeERC20&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;IERC20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;i_airdropToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;safeTransfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SafeERC20 is alibrary, it wrappers around ERC20 operations that throw on failure.if we can't for some reason send tokens to the address, it'll handle that for us.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;signing and verifying signatures&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;EIP&lt;/span&gt; &lt;span class="mi"&gt;191&lt;/span&gt;
&lt;span class="n"&gt;Ox19&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;EIP&lt;/span&gt; &lt;span class="mi"&gt;712&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="n"&gt;Ox01&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Ox19&lt;/span&gt; &lt;span class="mh"&gt;0x01&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;domainSeparator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;hashStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;domainSeparator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;hashStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eip712Domain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;eip712Domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;chainld&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;verifyingContract&lt;/span&gt;
&lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;salt&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_buildDomainSeparator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;keccak256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TYPE_HASH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_hashedName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_hashedVersion&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chainid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;EIP–712 is version 0x01 of EIP–191, it defines a standard of structured data signature，which solves the security and readability problems of signing raw data directly.&lt;/li&gt;
&lt;li&gt;EIP-191 standardizes what the sign data should look like. &lt;/li&gt;
&lt;li&gt;EIP-712 standardizes the format of the version specific data and the data to sign.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today I learn about merkle proof, then use it to airdrop tokens to users who are eligible.&lt;/p&gt;




&lt;h2&gt;
  
  
  lesson 13
&lt;/h2&gt;

&lt;h3&gt;
  
  
  26 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;ECDSA Singnatures&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ECDSA is used to:&lt;br&gt;
Generate key pairs&lt;br&gt;
Create Signatures&lt;br&gt;
Verify Signatures&lt;/p&gt;

&lt;p&gt;The specific curve used in ecdsa in ethereum is the setp256K1 curve.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cyfrin.io/blog/elliptic-curve-digital-signature-algorithm-and-signatures#1-ecdsa-key-generation-how-are-public-and-private-keys-created" rel="noopener noreferrer"&gt;The Elliptic Curve Digital Signature Algorithm (ECDSA)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;EIP-4844(Blob)&lt;/em&gt;-&amp;gt;[t=106061]&lt;/p&gt;

&lt;p&gt;Ethereum's Proto-Danksharding&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Blobs are a new transaction type that allows us to store data on-chain for a Short period of time.&lt;/li&gt;
&lt;li&gt;We can't access the data itself, but we can aocess a hash of the data with the new BLOBHASH opcode. &lt;/li&gt;
&lt;li&gt;Blobs were added because rollups wanted a cheaper way to validate transactions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🔹.&lt;em&gt;test claim&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;airdrop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getMessageHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amountToCollect&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// get the signature&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userPrivKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// gasPayer claims the airdrop for the user&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gasPayer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;airdrop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;claim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amountToCollect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;proof&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;use cast to sign msghash&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;cast&lt;/span&gt; &lt;span class="n"&gt;wallet&lt;/span&gt; &lt;span class="n"&gt;sign&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="n"&gt;MessageHash&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="n"&gt;xxx&lt;/span&gt;
&lt;span class="mh"&gt;0x04209f8dfd0ef06724e83d623207ba8c33b6690e08772f8887a4eaf9a66b9182188938adea374fa542ad5ddde24bdc981f5e26a628e65fb425a68db8a938f6761c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when you use cast wallet sign you create one one single signature however what we need is  v r s broken up individually.&lt;/p&gt;

&lt;p&gt;--no-hash: The message has already been hashed in the getMessageHash function.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Split Signature&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;splitSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;revert&lt;/span&gt; &lt;span class="n"&gt;__SplitSignatureScript__InvalidSignatureLength&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;assembly&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;mload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;96&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;tryRecover&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// receiving a hash of the original message&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;tryRecover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;recovered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RecoverError&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;errArg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// receives the `r` and `vs` short-signature fields separately.&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;tryRecover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;recovered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RecoverError&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;errArg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is normal to have more than one tryRecover in ECDSA.sol because they are Overloading.&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Today you learned about signing messages and verifying signatures through the program. Why do I get a different MessageHash from unit tests and cast call to getMessageHash with the same input parameters and the same MerkleAirdrop contract address? I can't get the same MessageHash no matter how I test it.&lt;/p&gt;




&lt;h2&gt;
  
  
  lesson 13
&lt;/h2&gt;

&lt;h3&gt;
  
  
  27 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 practice:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;test all on Anvil and sepolia&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# (0) 0xcd7559aab753f89e17d50b38712e1043bbbaccca (airdrop eligible)&lt;/span&gt;
&lt;span class="c"&gt;# (1) 0xfaa00ae9e0b9d5b4e25ce7c335cd1ce76969db63 (gas fee payer)&lt;/span&gt;

&lt;span class="c"&gt;# choose a address to be the airdrop claimer which is allowed to get the airdrop and put it into Interact.s.sol.&lt;/span&gt;

&lt;span class="c"&gt;# use the MakeMerkle.s.sol to recreate the Merkle Proof and root for this address, then put them into DeployMerkleAirdrop.s.sol and Interact.s.sol.&lt;/span&gt;

&lt;span class="c"&gt;# use DeployMerkleAirdrop.s.sol to deploy the two contract, mint token and transfer it to MerkleAirdrop.&lt;/span&gt;
forge script script/DeployMerkleAirdrop.s.sol:DeployMerkleAirdrop &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://eth-sepolia.g.alchemy.com/v2/xxx &lt;span class="nt"&gt;--private-key&lt;/span&gt; xxx &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;-vvvv&lt;/span&gt;
&lt;span class="c"&gt;# == Anvil Return ==&lt;/span&gt;
&lt;span class="c"&gt;# 0: contract MerkleAirdrop 0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82&lt;/span&gt;
&lt;span class="c"&gt;# 1: contract BagelToken 0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0&lt;/span&gt;

&lt;span class="c"&gt;# == Sepolia Return ==&lt;/span&gt;
&lt;span class="c"&gt;# 0: contract MerkleAirdrop 0xa571518aE1b329f7E9f968770e3A046bB6AAaad0&lt;/span&gt;
&lt;span class="c"&gt;# 1: contract BagelToken 0x06C96Bf66aBD9F767EE10A3E807E5a1a0Eb72F89&lt;/span&gt;

&lt;span class="c"&gt;# When an accident occurs during deployment, it not do mint and transfer, you can manually make up for it in this way&lt;/span&gt;
cast send 0x06C96Bf66aBD9F767EE10A3E807E5a1a0Eb72F89 &lt;span class="s2"&gt;"mint(address,uint256)"&lt;/span&gt; 0xa571518aE1b329f7E9f968770e3A046bB6AAaad0 100000000000000000000 &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://eth-sepolia.g.alchemy.com/v2/xxx &lt;span class="nt"&gt;--private-key&lt;/span&gt; xxx

&lt;span class="c"&gt;# call the getMessageHash to get MessageHash&lt;/span&gt;
cast call 0xa571518aE1b329f7E9f968770e3A046bB6AAaad0 &lt;span class="s2"&gt;"getMessageHash(address,uint256)"&lt;/span&gt; 0xcd7559aab753f89e17d50b38712e1043bbbaccca 25000000000000000000 &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://eth-sepolia.g.alchemy.com/v2/xxx

&lt;span class="c"&gt;# use privatekey to sign the MessageHash&lt;/span&gt;
cast wallet sign &lt;span class="nt"&gt;--no-hash&lt;/span&gt; 0xd448c2673189f6ff30d6f96d9f7ed07dc3fafbac96bbba5a44a059db35e4dfaa &lt;span class="nt"&gt;--private-key&lt;/span&gt; xxx

&lt;span class="c"&gt;# put the signture into Interact.s.sol&lt;/span&gt;
Use the rock to get boob to &lt;span class="nb"&gt;help &lt;/span&gt;jack get the airdrop

&lt;span class="c"&gt;# use Interact.s.sol to get (1) to claim airdrop for (0)&lt;/span&gt;
forge script script/Interact.s.sol:ClaimAirdrop &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://eth-sepolia.g.alchemy.com/v2/xxx &lt;span class="nt"&gt;--private-key&lt;/span&gt; xxx &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;-vv&lt;/span&gt;

&lt;span class="c"&gt;# check the airdrop token has been claimed&lt;/span&gt;
cast call 0x06C96Bf66aBD9F767EE10A3E807E5a1a0Eb72F89 &lt;span class="s2"&gt;"balanceOf(address)"&lt;/span&gt; 0xcd7559aab753f89e17d50b38712e1043bbbaccca &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://eth-sepolia.g.alchemy.com/v2/xxx
cast &lt;span class="nt"&gt;--to-dec&lt;/span&gt; 0x0000000000000000000000000000000000000000000000015af1d78b58c40000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Learned Merkle Trees and Signatures through a ClaimAirdrop contract, Basically know the application of Merkle Trees and how to sign the message and verify the signature in smart contract. Finally, test the whole process on the test network.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-14"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 14
&lt;/h2&gt;

&lt;h3&gt;
  
  
  28 Feb:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;way of upgrade smart contracts&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1.not really upgrading method or the parameterization method:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can't add new storage&lt;/li&gt;
&lt;li&gt;Can't add new logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2.social Yeet method or the migration method:&lt;/p&gt;

&lt;p&gt;People migrating and over into using this new one that the upgrade&lt;/p&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Truest to blockchain values&lt;/li&gt;
&lt;li&gt;Easiest to audit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lot of work to convince users to move&lt;/li&gt;
&lt;li&gt;Different addresses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3.Proxies&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Proxy Terminology:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whenever I want to upgrade I just deploy a new implementation contract and point my proxy to that new implementation. do contracts B's logic in contract A.&lt;/li&gt;
&lt;li&gt;all my storage variables are going to be stored in the proxy contract and not in the implementation contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;1.The Implementation Contract&lt;/p&gt;

&lt;p&gt;Which has all our code of our protocol. When we upgrade, we launch a brand new implemenation contract.&lt;/p&gt;

&lt;p&gt;2.The proxy contract.&lt;/p&gt;

&lt;p&gt;Which points to which implementation is the "correct"one, and routes everyone's function calls to that contract&lt;/p&gt;

&lt;p&gt;3.The user&lt;/p&gt;

&lt;p&gt;They make calls to the proxy&lt;/p&gt;

&lt;p&gt;4.The admin&lt;/p&gt;

&lt;p&gt;This is the user (or group of users/voters) who upgrade to new implementation contracts.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Gotchas:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;1.Storage Clashes&lt;/p&gt;

&lt;p&gt;this means we can only append new storage variables in new implementation contracts and we can't reorder or change old ones.&lt;/p&gt;

&lt;p&gt;2.Function Selector Clashes&lt;/p&gt;

&lt;p&gt;there are two ways to avoid this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transparent proxy pattern: in this methodology admins are only allowed to called admin functions and they can't call any functions in the implementation contract and users can only call functions in the implementation contract and not any admin contracts.&lt;/li&gt;
&lt;li&gt;Universal Upgradeable Proxies (UUPS Smart Contract Proxy Pattern)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;how upgrading actually works&lt;/em&gt; -&amp;gt;[t=110874]&lt;/p&gt;

&lt;p&gt;allows us to borrow functions and then no matter whatever variables name in contract A, it only saves according to the storage slots location and the other thing that's interesting is that even if you don't have variables it'll still save to storage slots.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;SmallProxy&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Proxy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1&lt;/span&gt;
    &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;_IMPLEMENTATION_SLOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setImplementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;newImplementation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;assembly&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;sstore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_IMPLEMENTATION_SLOT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newImplementation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_implementation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;implementationAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;assembly&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;implementationAddress&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_IMPLEMENTATION_SLOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// helper function&lt;/span&gt;
    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getDataToTransact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;numberToUpdate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;pure&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodeWithSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"setValue(uint256)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numberToUpdate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;readStorage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;valueAtStorageSlotZero&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;assembly&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;valueAtStorageSlotZero&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;ImplementationA&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnqcvr4lhb0fzqre81ey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjnqcvr4lhb0fzqre81ey.png" alt="Image description" width="645" height="682"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The "Transact" button is used to manually send any calldata to the contract, simulating a call invoke. &lt;/li&gt;
&lt;li&gt;But this contract has no setVule function, it will Trigger fallback() at the inherited Proxy contract and delegatecall logical contract. &lt;/li&gt;
&lt;li&gt;The Proxy reads the ImplementationA address in the storage and uses the calldata to executes delegatecall and finally executes ImplementationA.setValue(777).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;Implementation(logical) Contract Initialize&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;Logic&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Initializable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UUPSUpgradeable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OwnableUpgradeable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_disableInitializers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;initializer&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Ownable_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//sets owner to: owner = msg. sender&lt;/span&gt;
        &lt;span class="n"&gt;UUPSUpgradeable_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;//to say this is a upps upgradable contract &lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Constructors are not used in Implementation Contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In Proxy mode, storage variables are stored in proxy contracts, not logical contracts. &lt;/li&gt;
&lt;li&gt;However, if the logical contract has a constructor, its storage will only be initialized in its own storage space and cannot be stored in the Proxy contract. &lt;/li&gt;
&lt;li&gt;So you should have the Proxy call initialize() of the logical contract to set the initial value after the proxy contract is deployed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;The key of upgrade contract is to know the use of Initializable, OwnableUpgradeable and UUPSUpgradeable. Figure out the relationship between proxy contracts and logical contracts.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-15"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 15
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1 Mar:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;smart contract account (SCA &amp;amp; AA account)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsz0ozjenxg9kaiqifpax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsz0ozjenxg9kaiqifpax.png" alt="Image description" width="800" height="304"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1pyizpcslyka9mgby2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1pyizpcslyka9mgby2m.png" alt="Image description" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;These alt-memepol nodes are going to deploy your contract for you it's going to always be routed through this EntryPoint.sol which is going to do something validation and then it's going to be routed to your smart contract account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;it's EntryPoint.sol that handles every single account abstraction user operations sent, all of these alt-memepol nodes calling this contract call this function called handleOps.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;instead of sending a regular transaction object to the blockchain, those alt-mempool nodes will send a useroperation to the entrypoint Dos contract which will call handleOps() to call your contract and call the custom logic that you built in your validateUserOp().&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-4337" rel="noopener noreferrer"&gt;eip-4337&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;create a MinimalAccount.sol&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @ztmy whenever we send a user operation(UserOp) to the entrypoint, it need to call this execute function to call the DAPP&lt;/span&gt;
&lt;span class="c1"&gt;// @ztmy the owner of this minimal account can be our EOA account(Direct call)  or it can be the entry point.&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;functionData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;requireFromEntryPointOrOwner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;functionData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;revert&lt;/span&gt; &lt;span class="n"&gt;MinimalAccount__CallFailed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// A signature is valid, if it's the MinimalAccount owner&lt;/span&gt;
&lt;span class="c1"&gt;// @ztmy this is the function that the entrypoint contract is going to be calling&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;validateUserOp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PackedUserOperation&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;userOp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;userOpHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;missingAccountFunds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;external&lt;/span&gt;
    &lt;span class="n"&gt;requireFromEntryPoint&lt;/span&gt;
    &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;validationData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// @ztmy use userOp.signature to valid the userOpHash&lt;/span&gt;
    &lt;span class="n"&gt;validationData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_validateSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userOp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userOpHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// _validateNonce()&lt;/span&gt;
    &lt;span class="n"&gt;_payPrefund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;missingAccountFunds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MinimalAccount.sol is a smart contract account, above are two core functions of it.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;test direct call the execute&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// @ztmy whenever we send a user operation(UserOp) to the entrypoint, it need to call this execute function to call the DAPP&lt;/span&gt;
&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;calldata&lt;/span&gt; &lt;span class="n"&gt;functionData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;external&lt;/span&gt; &lt;span class="n"&gt;requireFromEntryPointOrOwner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;functionData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;revert&lt;/span&gt; &lt;span class="n"&gt;MinimalAccount__CallFailed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// core of test:&lt;/span&gt;
&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usdc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;functionData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodeWithSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERC20Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;AMOUNT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Act&lt;/span&gt;
&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;functionData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the owner of this minimal account can be our EOA account(Direct call)  or it can be the entry point.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;create SendPackedUserOp.s.sol&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Generate the unsigned data&lt;/span&gt;
&lt;span class="c1"&gt;// @ztmy Fill the parameters in the PackedUserOperation struct,  except for signature.&lt;/span&gt;
&lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getNonce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;PackedUserOperation&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;userOp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_generateUnsignedUserOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Get the userOp Hash&lt;/span&gt;
&lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;userOpHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IEntryPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entryPoint&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;getUserOpHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userOp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// @ztmy Convert the Hash to ERC-191 format digest&lt;/span&gt;
&lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userOpHash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toEthSignedMessageHash&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Sign it&lt;/span&gt;
&lt;span class="c1"&gt;// @ztmy sign the userOpHash then add it to userOp&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;userOp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodePacked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Note the order&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create SendPackedUserOp.s.sol to create the parameter PackedUserOperation, which is what the alt-mempool needs to get. &lt;/li&gt;
&lt;li&gt;SendPackedUserOp.s.sol do these three things in step.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;test validateUserOp can be seccess called by entrypoint&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;testValidationOfUserOps&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
    &lt;span class="n"&gt;assertEq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usdc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usdc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// @ztmy Firstly our contract call usdc mint()&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;functionData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodeWithSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ERC20Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;AMOUNT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// @ztmy Then entrypoint contract call our contract execute() to execute mint()&lt;/span&gt;
    &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;executeCallData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodeWithSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MinimalAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;functionData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;PackedUserOperation&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;packedUserOp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sendPackedUserOp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generateSignedUserOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;executeCallData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;helperConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getConfig&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// @ztmy EntryPoint.getUserOpHash() will hash the packedUserOp exclude the signature.&lt;/span&gt;
    &lt;span class="n"&gt;bytes32&lt;/span&gt; &lt;span class="n"&gt;userOperationHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IEntryPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;helperConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getConfig&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;entryPoint&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;getUserOpHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packedUserOp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;missingAccountFunds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1e18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Act&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;prank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;helperConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getConfig&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;entryPoint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;validationData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;minimalAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;validateUserOp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;packedUserOp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userOperationHash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;missingAccountFunds&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// @ztmy probably should parse the validationdata but since our codebase is pretty simple &lt;/span&gt;
    &lt;span class="c1"&gt;// and we just know it's returning a one or a zero (SIG_VALIDATION_SUCCESS == 0)&lt;/span&gt;
    &lt;span class="n"&gt;assertEq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validationData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;It's going to be these alt-mempo nodes who are going to submit the transaction to the entrypoint.&lt;/li&gt;
&lt;li&gt;The entrypoint is going to call validateUserOp() to validate a transaction on our account. &lt;/li&gt;
&lt;li&gt;Then it's going to pass the transaction information to our account and then our account will be the message.sender and it need to call the execute() to call the DAPP.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Learned the working process of a smart contract account, and how to create a simple one.&lt;/p&gt;




&lt;h2&gt;
  
  
  lesson 15
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2 Mar:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;Mempool&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bundler is the Mempool processor for ERC-4337 transactions, equivalent to "Alt-Mempool".&lt;/li&gt;
&lt;li&gt;Ordinary transactions enter the public Mempool, from which miners/validators select transactions.&lt;/li&gt;
&lt;li&gt;The UserOperation enters Bundler (private Mempool), which is then uniformly committed by Bundler to the EntryPoint contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔹.&lt;em&gt;ZK Sync system contracts&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ZK Sync has a lot of system contracts at very specific addresses that govern a lot of the functionality that goes on in zync. the contract deployer being one of the most important ones, this is also why when trying to deploy a smart contract to ZK sync we can have a hard time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NonceHolder system contract&lt;/strong&gt; has a mapping of every single account every single account address and the nonce that they currently are working with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;bootloader system contract&lt;/strong&gt; you can kind of think as like the super admin system contract of all these system contracts. &lt;br&gt;
Whenever you send this type 1113 transaction it will be rerouted to this, this is how ZK sync has account abstraction built in. &lt;br&gt;
You can kind of think of this as the entry point smart contract on ethereum mainnet. &lt;br&gt;
the message. sender is always going to be this.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Lifecycle of a Type 113 (0x71) Transaction on ZK Sync&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;msg.sender is the bootloader system contract&lt;/p&gt;

&lt;p&gt;Phase 1: Validation&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Sends Transaction&lt;/strong&gt;: The user sends the transaction to the "zkSync API client" (a type of "light node").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce Check&lt;/strong&gt;: The zkSync API client checks if the nonce is unique by querying the &lt;code&gt;NonceHolder&lt;/code&gt; system contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate Transaction&lt;/strong&gt;: The zkSync API client calls &lt;code&gt;validateTransaction&lt;/code&gt;, which &lt;strong&gt;must&lt;/strong&gt; update the nonce.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nonce Update Verification&lt;/strong&gt;: The zkSync API client verifies that the nonce has been updated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payment Handling&lt;/strong&gt;: The zkSync API client calls either:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;payForTransaction&lt;/code&gt;, or&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;prepareForPaymaster&lt;/code&gt; &amp;amp; &lt;code&gt;validateAndPayForPaymasterTransaction&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bootloader Payment Verification&lt;/strong&gt;: The zkSync API client ensures that the bootloader is paid.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: All validation steps occur on the "light node" (API client). The ZK Sync system consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Light Nodes&lt;/strong&gt; (API client nodes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Main Node&lt;/strong&gt; (the main sequencer node, which is currently centralized but will be decentralized in the future).&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Phase 2: Execution&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Transaction Submission&lt;/strong&gt;: The zkSync API client passes the validated transaction to the main node / sequencer (currently the same entity).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute Transaction&lt;/strong&gt;: The main node calls &lt;code&gt;executeTransaction&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-Transaction (if applicable)&lt;/strong&gt;: If a paymaster was used, the &lt;code&gt;postTransaction&lt;/code&gt; function is called.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;recap of all the things -&amp;gt;[t=124316]&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;Call System Contract&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# set this up then zk sync will allow you call the systems contract&lt;/span&gt;
is-system &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;SystemContractsCaller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;systemCallWithPropagatedRevert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;uint32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gasleft&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
    &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NONCE_HOLDER_SYSTEM_CONTRACT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encodeCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INonceHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;incrementMinNonceIfEquals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;on ZK sync there are a lot of admin smart contracts called system smart contracts where they have admin level power that over the global of the chain.&lt;/p&gt;

&lt;p&gt;this is what's known as a system call simulation&lt;/p&gt;

&lt;p&gt;Tips: they actually have an AI that has read all of their documentation that does a pretty good job of answering questions related specifically to ZK sync docs it's in the Discord it's a great tool&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;comparison&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ZK Sync Node == Alt-Mempool&lt;/p&gt;

&lt;p&gt;bootloader == entrypoint&lt;/p&gt;

&lt;p&gt;(struct) Transaction == PackedUserOperation&lt;/p&gt;

&lt;p&gt;validateUserOp == validateTransaction&lt;/p&gt;

&lt;p&gt;entrypoint based account abstraction the from is going to be whatever node or user actually created the transaction whereas on zync with Native account abstraction the from is actually going to be the smart contract wallet itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bundler sends UserOperation  → entrypoint &lt;/li&gt;
&lt;li&gt;SCA direct sends EIP-712 Signature transaction(113) → Bootloader &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;From this lesson, I learned how to do account abstraction on a chain that doesn't have native account abstraction but has account abstraction via an entrypoint smart contract and an Alt-Mempool, then also learned how to do account abstraction on a chain that has a account abstraction built in.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-16"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 16
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3 Mar:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

&lt;p&gt;🔹.&lt;em&gt;DAO&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Voting Mechanism
Token based voting
Skin in the game voting
Proof of personhood or participation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;put the implementation of the voting into two categories: &lt;br&gt;
onchain voting and offchain voting&lt;/p&gt;

&lt;p&gt;Aragon: &lt;br&gt;
A set of tools and infrastructure is provided to enable users to create and manage DAOs without code required.&lt;/p&gt;

&lt;p&gt;🔹.&lt;em&gt;some feature&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Checkpoint：&lt;/span&gt;
&lt;span class="c1"&gt;// Make sure to use the voting weights that were used when the proposal was created&lt;/span&gt;
&lt;span class="c1"&gt;// Subsequent token transfers do not affect voting rights&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Checkpoint&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;uint32&lt;/span&gt; &lt;span class="n"&gt;fromBlock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   
    &lt;span class="n"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;votes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Each address has its own checkpoint history&lt;/span&gt;


&lt;span class="c1"&gt;// Activate voting rights, will effect at the next block&lt;/span&gt;
&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;VOTER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="c1"&gt;// permission setting&lt;/span&gt;
&lt;span class="c1"&gt;// 1. Anyone can submit a proposal to the Governor&lt;/span&gt;
&lt;span class="c1"&gt;// 2. After the proposal is passed, only the Governor can submit an execution plan to TimeLock&lt;/span&gt;
&lt;span class="n"&gt;timelock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grantRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;proposerRole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;governor&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// anybody can execute a past proposal&lt;/span&gt;
&lt;span class="n"&gt;timelock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;grantRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;executorRole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// Remove administrator rights&lt;/span&gt;
&lt;span class="n"&gt;timelock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;revokeRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;adminRole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// TimeLock is responsible for execution as the owner of Box&lt;/span&gt;
&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transferOwnership&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timelock&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔹.&lt;em&gt;process of DAO&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;MyGovernor Contract:&lt;br&gt;
Proposal creation and management, vote management&lt;/p&gt;

&lt;p&gt;TimeLock Contract:&lt;br&gt;
Delay execution, hold authority on other contracts, and finally execute the proposal&lt;/p&gt;

&lt;p&gt;Governor(Create proposal, manage vote) -&amp;gt; TimeLock(Delay, execute)&lt;/p&gt;

&lt;p&gt;the process of voting of a typical DAO:&lt;/p&gt;

&lt;p&gt;1.Propose to the DAO &lt;/p&gt;

&lt;p&gt;Voting Delay (Delay since proposal is created until voting starts)&lt;/p&gt;

&lt;p&gt;2.Vote &lt;/p&gt;

&lt;p&gt;Voting Period&lt;/p&gt;

&lt;p&gt;3.Queue &lt;/p&gt;

&lt;p&gt;min Delay (Delay that you have to wait before executing)&lt;/p&gt;

&lt;p&gt;4.Execute&lt;/p&gt;

&lt;h4&gt;
  
  
  📌 sum &amp;amp; F:
&lt;/h4&gt;

&lt;p&gt;Have a basic understanding of DAO and the process of voting.&lt;/p&gt;




&lt;p&gt;&lt;a id="lesson-17"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  lesson 17
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4 Mar:
&lt;/h3&gt;

&lt;h4&gt;
  
  
  📌 harvest:
&lt;/h4&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>solidity</category>
      <category>foundry</category>
    </item>
  </channel>
</rss>
