<?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>Forem: cyril</title>
    <description>The latest articles on Forem by cyril (@chainparser).</description>
    <link>https://forem.com/chainparser</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%2F1868741%2F91782fd1-b7b5-4d20-bf40-cae2c6266175.png</url>
      <title>Forem: cyril</title>
      <link>https://forem.com/chainparser</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/chainparser"/>
    <language>en</language>
    <item>
      <title>Introducing Revenant: A Dollar-Cost Averaging Spot Trading Bot for Hyperliquid DEX.</title>
      <dc:creator>cyril</dc:creator>
      <pubDate>Mon, 13 Apr 2026 13:43:13 +0000</pubDate>
      <link>https://forem.com/chainparser/introducing-revenant-a-dollar-cost-averaging-spot-trading-bot-for-hyperliquid-dex-264e</link>
      <guid>https://forem.com/chainparser/introducing-revenant-a-dollar-cost-averaging-spot-trading-bot-for-hyperliquid-dex-264e</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/chainparser/revenant" rel="noopener noreferrer"&gt;Revenant&lt;/a&gt; is a lightweight, open-source DCA (Dollar-Cost-Averaging) spot trading bot for &lt;a href="https://app.hyperliquid.xyz" rel="noopener noreferrer"&gt;Hyperliquid&lt;/a&gt; decentralized exchange, written entirely in Python.&lt;/p&gt;

&lt;p&gt;It automates recurring spot market buys at configurable intervals, with built-in position sizing, take-profit logic, and real-time status monitoring using the official &lt;a href="https://github.com/hyperliquid-dex/hyperliquid-python-sdk/tree/master" rel="noopener noreferrer"&gt;Hyperliquid Python SDK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The bot was designed from the ground up for simplicity, reliability, and zero-maintenance operation.&lt;/p&gt;

&lt;p&gt;This documentation walks through the full development and deployment journey, from initial setup and core trading logic to packaging it as a clean Flask app and launching it as a managed web service on &lt;a href="https://cloud.digitalocean.com" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; App Platform in minutes.&lt;/p&gt;

&lt;p&gt;By following this documentation, anyone can run the bot as-is, customize it for their own strategy, or learn how to build and deploy similar trading tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  Initial Skeletal Setup
&lt;/h2&gt;

&lt;p&gt;Before any trading logic, we start with the smallest possible Flask application. This confirms that the project structure, build process, and DigitalOcean App Platform configuration are working correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project Structure (Root Folder)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;revenant/
├── app.py
├── requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Files&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;app.py&lt;/code&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&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="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello World!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Optional: only used when running locally with `python app.py`
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PORT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&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;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;port&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;requirements.txt&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flask
gunicorn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, deploy the app on DigitalOcean App Platform.&lt;/p&gt;

&lt;p&gt;First, create a new GitHub repository (eg. &lt;code&gt;revenant&lt;/code&gt;) and push the two files above to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;Head over to the &lt;a href="https://cloud.digitalocean.com" rel="noopener noreferrer"&gt;DigitalOcean Control Panel&lt;/a&gt;, navigate to &lt;strong&gt;App Platform&lt;/strong&gt;, then click on &lt;strong&gt;Create app&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%2Fy7g17ia00zkf83rli6u9.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%2Fy7g17ia00zkf83rli6u9.png" alt=" " width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connect your GitHub account, select the relevant repository, and the &lt;code&gt;main&lt;/code&gt; branch. App Platform will automatically detect the Python app.&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%2Ft5u5up9ffo25ezjvm3b9.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%2Ft5u5up9ffo25ezjvm3b9.png" alt=" " width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Web Service&lt;/strong&gt; component settings, set the run command as &lt;code&gt;gunicorn --worker-tmp-dir /dev/shm app:app&lt;/code&gt;, and leave the build command empty.&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%2Ffxxkc25ip4yjcy19mags.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%2Ffxxkc25ip4yjcy19mags.png" alt=" " width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Create App&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the build finishes, your app will be live at a URL similar to &lt;code&gt;https://revenant-xxxxx.ondigitalocean.app&lt;/code&gt;. You should see a plain white page with the text &lt;strong&gt;Hello World!&lt;/strong&gt; exactly as shown below:&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%2Fg2q4lh5eymdxzsiwfahm.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%2Fg2q4lh5eymdxzsiwfahm.png" alt=" " width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This confirms the deployment pipeline is working. From here, we can safely start building the actual DCA trading logic for Revenant without worrying about infrastructure issues.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Hyperliquid Utilities
&lt;/h2&gt;

&lt;p&gt;Now, let's add the trading helper functions that interact with the Hyperliquid DEX. These utilities handle authentication, balance checks, price fetching, and executing market buy/sell orders for the relevant spot pair.&lt;/p&gt;

&lt;p&gt;All sensitive data (especially the private key) is loaded from environment variables. Keys are never to be committed to Git.&lt;/p&gt;

&lt;p&gt;Create a new Python file in the root directory (&lt;code&gt;utility.py&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;revenant/
├── app.py
├── requirements.txt
├── utility.py          ← new file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the new &lt;code&gt;utility.py&lt;/code&gt; file, add the following code:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;eth_account&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;hyperliquid.info&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Info&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;hyperliquid.exchange&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Exchange&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;hyperliquid.utils&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;constants&lt;/span&gt;

&lt;span class="c1"&gt;# Load private key from environment variable (required for DigitalOcean)
&lt;/span&gt;&lt;span class="n"&gt;HL_PRIVATE_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HL_PRIVATE_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;HL_PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HL_PRIVATE_KEY environment variable is not set!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Authentication
&lt;/span&gt;&lt;span class="n"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eth_account&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="nf"&gt;from_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HL_PRIVATE_KEY&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;wallet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize exchange for placing orders
&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Exchange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MAINNET_API_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;account_address&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="c1"&gt;# Initialize info client for reading data (REST only)
&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MAINNET_API_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skip_ws&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Get USDC and HYPE balances (available balance = total - hold)
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_balances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spot_user_state&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wallet&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;balances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;state&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;balances&lt;/span&gt;&lt;span class="sh"&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;quote_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="n"&gt;base_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;balances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;coin&lt;/span&gt;&lt;span class="sh"&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;QUOTE_ASSET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;quote_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;float&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;coin&lt;/span&gt;&lt;span class="sh"&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;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;base_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;float&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hold&lt;/span&gt;&lt;span class="sh"&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;quote_balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_balance&lt;/span&gt;

&lt;span class="c1"&gt;# Get current HYPE price from mid price
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;all_mids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all_mids&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;all_mids&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="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="c1"&gt;# Execute market sell of HYPE
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_sell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;sell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;market_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;is_buy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;slippage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.002&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;sell&lt;/span&gt;

&lt;span class="c1"&gt;# Execute market buy of HYPE with USDC amount
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute_buy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;buy_size_usdc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;get_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Could not fetch &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buy_size_usdc&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;get_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;buy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;market_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;is_buy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;sz&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;slippage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.002&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;buy&lt;/span&gt;

&lt;span class="c1"&gt;# Get the most recent fill (useful for logging/tracking)
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_most_recent_fill&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;fills&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;user_fills&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;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;fills&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fills&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update the &lt;code&gt;requirements.txt&lt;/code&gt; file to reflect the newly added libraries, &lt;code&gt;hyperliquid-python-sdk&lt;/code&gt;, &lt;code&gt;eth-account&lt;/code&gt;, and &lt;code&gt;protobuf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flask
gunicorn
hyperliquid-python-sdk
eth-account
protobuf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following the introduction of a new environment variable, let's update DigitalOcean's Environment Variables.&lt;/p&gt;

&lt;p&gt;Go to your app in the DigitalOcean control panel and click "&lt;strong&gt;Edit&lt;/strong&gt;" on the &lt;strong&gt;Web Service&lt;/strong&gt; component. Scroll to Environmental Variables and add a new variable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Key: HL_PRIVATE_KEY&lt;/li&gt;
&lt;li&gt;Value: 0x...&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%2Fea4qpsexswrzthtie4tw.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%2Fea4qpsexswrzthtie4tw.png" alt=" " width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click Save → Deploy (or let it auto-deploy on push).&lt;/p&gt;




&lt;h2&gt;
  
  
  Core DCA Trading Logic
&lt;/h2&gt;

&lt;p&gt;We now replace the minimal "Hello World" Flask app with a complete trading engine for Revenant. &lt;/p&gt;

&lt;p&gt;The bot implements a simple but effective DCA strategy on the HYPE/USDC spot pair:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buys $10 worth of HYPE on every run (unless USDC balance is too low).&lt;/li&gt;
&lt;li&gt;Continuously averages the buy price.&lt;/li&gt;
&lt;li&gt;When the current price reaches +3% the average buy price, it sells the entire HYPE position, records the PnL, and starts a new session.&lt;/li&gt;
&lt;li&gt;All states are tracked in a global counter dictionary (in-memory for now).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full &lt;code&gt;app.py&lt;/code&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="c1"&gt;# Add background scheduler imports
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apscheduler.schedulers.background&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BackgroundScheduler&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;atexit&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&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;# Define global variables
&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_buy_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_sessions&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buy_size_usdc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buy_count&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_buy_trades&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_volume_usdc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.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;BASE_ASSET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HYPE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;USDC&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/execute&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;

    &lt;span class="c1"&gt;# Initialize status
&lt;/span&gt;    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

    &lt;span class="c1"&gt;# Fetch current market data, update AUM
&lt;/span&gt;    &lt;span class="n"&gt;quote_balance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_balances&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_price&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;AUM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;quote_balance&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="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Save balances
&lt;/span&gt;    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;base_balance&lt;/span&gt;&lt;span class="sh"&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;base_balance&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quote_balance&lt;/span&gt;&lt;span class="sh"&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;quote_balance&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&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;price&lt;/span&gt;
    &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AUM&lt;/span&gt;&lt;span class="sh"&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;AUM&lt;/span&gt;

    &lt;span class="c1"&gt;# Start/continue trading
&lt;/span&gt;    &lt;span class="c1"&gt;# Check if sell condition is met.
&lt;/span&gt;    &lt;span class="n"&gt;sell_condition_is_met&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_buy_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.03&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_buy_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nf"&gt;float&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;sell_condition_is_met&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

    &lt;span class="c1"&gt;# if sell condition is met, liquidate hype position, end session, and start a new session. else keep buying.
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;sell_condition_is_met&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# liquidate hype position (sell all of hype balance)
&lt;/span&gt;        &lt;span class="n"&gt;sell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute_sell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# get fill price and calculate pnl in usdc
&lt;/span&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;most_recent_fill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_most_recent_fill&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;avg_fill_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;most_recent_fill&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;px&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;pnl_usdc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avg_fill_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_buy_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;base_balance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# (avg fill price - avg buy price) * total hype bought
&lt;/span&gt;
        &lt;span class="c1"&gt;# update counter
&lt;/span&gt;        &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pnl_usdc&lt;/span&gt;&lt;span class="sh"&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;pnl_usdc&lt;/span&gt;
        &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_sessions&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_volume_usdc&lt;/span&gt;&lt;span class="sh"&gt;"&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="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avg_fill_price&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_trade&lt;/span&gt;&lt;span class="sh"&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;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sell condition met, HYPE holdings sold.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# keep buying with a constant size of $10
&lt;/span&gt;        &lt;span class="n"&gt;buy_size_usdc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buy_size_usdc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Execute buy if buy size is less than or equal to the available balance
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;buy_size_usdc&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;quote_balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

            &lt;span class="c1"&gt;# execute buy
&lt;/span&gt;            &lt;span class="n"&gt;buy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute_buy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;QUOTE_ASSET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buy_size_usdc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

            &lt;span class="c1"&gt;# wait 5 seconds, get most recent fill details
&lt;/span&gt;            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;most_recent_fill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_most_recent_fill&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;avg_fill_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;most_recent_fill&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;px&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_buy_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;float&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;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_buy_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avg_fill_price&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;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_buy_price&lt;/span&gt;&lt;span class="sh"&gt;"&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="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_buy_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avg_fill_price&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="c1"&gt;# Update counter
&lt;/span&gt;            &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buy_count&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_buy_trades&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_volume_usdc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buy_size_usdc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_trade&lt;/span&gt;&lt;span class="sh"&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;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sell condition not met, buy executed.&lt;/span&gt;&lt;span class="sh"&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;status&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Sell condition not met, balance low.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# buy nothing when balance low, wait for next 15 minutes
&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="c1"&gt;# ── Background Scheduler (runs automatically every hour) ──
&lt;/span&gt;&lt;span class="n"&gt;scheduler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BackgroundScheduler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scheduled_execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Wrapper that runs the trading cycle from the background job.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;app_context&lt;/span&gt;&lt;span class="p"&gt;():&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;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_job&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;scheduled_execute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;trigger&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;interval&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hours&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="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;revenant_dca_cycle&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;replace_existing&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Gracefully shut down scheduler when the app exits
&lt;/span&gt;&lt;span class="n"&gt;atexit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Optional: only used when running locally with `python app.py`
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PORT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&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;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How the Strategy Works (Summary)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Condition&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Buy&lt;/td&gt;
&lt;td&gt;Price &amp;lt; 3% avg_buy_price&lt;/td&gt;
&lt;td&gt;Buy $10 USDC of HYPE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sell (Take profit)&lt;/td&gt;
&lt;td&gt;Price ≥ 3% avg_buy_price&lt;/td&gt;
&lt;td&gt;Sell all HYPE, record PnL, reset session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No-op&lt;/td&gt;
&lt;td&gt;Insufficient USDC balance&lt;/td&gt;
&lt;td&gt;Wait for next cycle&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Next, let's add a background scheduler (APScheduler) so the bot automatically runs the &lt;code&gt;/execute&lt;/code&gt; endpoint every 1 hour.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automatic Trading Every Hour
&lt;/h2&gt;

&lt;p&gt;Add a background scheduler using &lt;strong&gt;APScheduler&lt;/strong&gt; so Revenant automatically runs the full DCA trading cycle (&lt;code&gt;/execute&lt;/code&gt; logic) every 1 hour. No manual calls or external cron jobs required.&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;APScheduler&lt;/code&gt; to the &lt;code&gt;requirements.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flask
gunicorn
hyperliquid
eth-account
APScheduler
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, add background scheduler imports:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;apscheduler.schedulers.background&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BackgroundScheduler&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;atexit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add the scheduler code beneath the trade logic execution:&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;# ── Background Scheduler (runs automatically every hour) ──
&lt;/span&gt;&lt;span class="n"&gt;scheduler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BackgroundScheduler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scheduled_execute&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Wrapper that runs the trading cycle from the background job.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;app_context&lt;/span&gt;&lt;span class="p"&gt;():&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;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_job&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;scheduled_execute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;trigger&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;interval&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hours&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="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;revenant_dca_cycle&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;replace_existing&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Gracefully shut down scheduler when the app exits
&lt;/span&gt;&lt;span class="n"&gt;atexit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;scheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wait&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update Run command on DigitalOcean
&lt;/h3&gt;

&lt;p&gt;To prevent the scheduler from starting multiple times (Gunicorn forks workers by default):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your app in DigitalOcean Control Panel → Components → your Web Service → Edit.&lt;/li&gt;
&lt;li&gt;Change the Run command to: &lt;code&gt;gunicorn --worker-tmp-dir /dev/shm --preload --workers=1 app:app&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save and Redeploy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;--preload&lt;/code&gt; flag ensures the scheduler is created only once before workers are forked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Current Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;State is stored only in memory → resets when the app restarts.&lt;/li&gt;
&lt;li&gt;No error handling or retry logic around API calls yet.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Revenant is now a fully functional, automated DCA spot-trading bot running live on the DigitalOcean App Platform.&lt;/p&gt;

&lt;p&gt;It connects securely to Hyperliquid, executes $10 USDC buys every hour, tracks average entry price, and automatically takes profit by selling the entire position when the price doubles.&lt;/p&gt;

&lt;p&gt;The entire project uses a minimal, clean Flask + APScheduler setup that deploys in minutes and requires zero server management. &lt;/p&gt;

&lt;p&gt;This is a solid foundation to extend: add persistent storage, configurable parameters via environment variables, a web dashboard, error alerts, or even multi-pair support.&lt;/p&gt;

</description>
      <category>dca</category>
      <category>bot</category>
      <category>hyperliquid</category>
      <category>crypto</category>
    </item>
    <item>
      <title>Implementing Off-Chain Indexing in Polkadot Substrate for Optimized Data Retrieval and Storage</title>
      <dc:creator>cyril</dc:creator>
      <pubDate>Mon, 06 Apr 2026 04:03:14 +0000</pubDate>
      <link>https://forem.com/chainparser/implementing-off-chain-indexing-in-polkadot-substrate-for-optimized-data-retrieval-and-storage-dcn</link>
      <guid>https://forem.com/chainparser/implementing-off-chain-indexing-in-polkadot-substrate-for-optimized-data-retrieval-and-storage-dcn</guid>
      <description>&lt;p&gt;With over 600 ecosystem projects and 632k+ max transaction throughput, &lt;a href="https://polkadot.com/" rel="noopener noreferrer"&gt;Polkadot&lt;/a&gt; has become one of the major blockchains with a thriving ecosystem. Building on Polkadot is fairly straightforward via the &lt;a href="https://github.com/paritytech/polkadot-sdk" rel="noopener noreferrer"&gt;Polkadot SDK&lt;/a&gt;. The SDK is a versatile developer kit designed to facilitate building on the Polkadot network by making the required components for building chains, parachains, rollups, and more available to interested developers. &lt;/p&gt;

&lt;p&gt;The Polkadot SDK is composed of five major components made up of Substrate, FRAME, Cumulus, XCM, and the node implementation protocol. &lt;a href="https://paritytech.github.io/polkadot-sdk/master/polkadot_sdk_docs/polkadot_sdk/substrate/index.html" rel="noopener noreferrer"&gt;Substrate&lt;/a&gt; is a highly customizable Rust framework for building application-specific chains from modular and extensible components. It includes default implementations of core infrastructure components, allowing developers to focus on application logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="/assets/images/polkadot-sdk.png" class="article-body-image-wrapper"&gt;&lt;img src="/assets/images/polkadot-sdk.png" alt="Polkadot SDK"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As chains mature and handle increasingly complex data and higher transaction volumes, the efficiency of data retrieval and storage becomes paramount for maintaining performance and scalability. Traditional on-chain data storage, while providing immutability and transparency, can become a bottleneck when dealing with frequent and complex queries, especially for large datasets. &lt;/p&gt;

&lt;p&gt;To address these challenges, &lt;a href="https://github.com/JoshOrndorff/substrate-recipes/blob/master/text/off-chain-workers/indexing.md" rel="noopener noreferrer"&gt;off-chain indexing&lt;/a&gt; presents a compelling solution for optimizing data handling in Substrate-based chains. This guide aims to provide a thorough understanding of off-chain indexing within the Polkadot ecosystem, offering detailed implementation guidance and exploring the various considerations for its effective utilization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Substrate provides a highly flexible and modular environment for blockchain development. Traditionally, blockchain data resides on-chain, ensuring immutability and network-wide consensus. However, for applications dealing with large datasets or requiring complex and frequent queries, this on-chain paradigm can become a performance bottleneck and significantly increase storage costs.&lt;/p&gt;

&lt;p&gt;&lt;a href="/assets/images/substrate-node.png" class="article-body-image-wrapper"&gt;&lt;img src="/assets/images/substrate-node.png" alt="Polkadot Node"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical Terms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;On-chain Storage&lt;/strong&gt;: Data that is stored directly on the chain and is part of the network's state, secured by consensus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Off-chain Storage&lt;/strong&gt;: Data that is stored outside the main chain, typically on individual nodes' local storage or external databases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Offchain Workers (OCWs)&lt;/strong&gt;: Substrate's feature allowing for the execution of long-running, potentially non-deterministic tasks off the main chain, with the ability to read on-chain state and interact with the external world.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Off-chain Indexing&lt;/strong&gt;: A Substrate feature enabling the runtime to directly write data to a node's local off-chain storage, which can then be queried by Offchain Workers or via RPC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Runtime&lt;/strong&gt;: The state transition logic of a Substrate-based chain, defining how the chain's state changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Extrinsic&lt;/strong&gt;: A signed transaction that can trigger state changes in the chain's runtime.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In today's rapidly evolving tech landscape, chain applications are moving beyond simple token transfers to power complex ecosystems like &lt;a href="https://www.investopedia.com/decentralized-finance-defi-5113835" rel="noopener noreferrer"&gt;DeFi&lt;/a&gt;, &lt;a href="https://www.investopedia.com/non-fungible-tokens-nft-5115211" rel="noopener noreferrer"&gt;NFTs&lt;/a&gt;, and &lt;a href="https://sopa.tulane.edu/blog/decentralized-social-networks" rel="noopener noreferrer"&gt;decentralized social media&lt;/a&gt;. These applications generate vast amounts of data, and efficient data retrieval is crucial for user experience, analytics, and overall platform scalability. Off-chain indexing offers a vital tool to decouple frequently queried or derived data from the core, expensive on-chain storage, leading to faster query times, reduced on-chain storage burden, and the ability to support more sophisticated data-driven features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Power of Off-Chain Indexing in Substrate
&lt;/h3&gt;

&lt;p&gt;Substrate's off-chain indexing allows the chain's runtime logic itself to write data directly to the local storage of the node executing that logic. This is distinct from off-chain workers performing external computations and then submitting transactions. The data written through off-chain indexing is not subject to the same consensus mechanisms as on-chain data, making writes significantly faster and less resource-intensive. This indexed data can then be accessed by off-chain workers for further processing or served via custom RPC endpoints.&lt;/p&gt;

&lt;p&gt;Consider a decentralized marketplace where users create listings with numerous attributes (&lt;code&gt;price&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;categories&lt;/code&gt;, etc.). Storing and querying all these attributes directly on-chain for every search can be inefficient. With off-chain indexing, when a new listing is created (an on-chain event), the runtime can extract relevant attributes and write them to the off-chain storage, indexed for efficient searching. An Offchain Worker or a custom RPC handler can then query this off-chain index to quickly retrieve listings based on various criteria without needing to iterate through all on-chain events.&lt;/p&gt;

&lt;p&gt;This direct write capability from the runtime provides a highly efficient way to create searchable and filterable datasets derived from on-chain events or state changes. It offloads query-intensive tasks from the core chain, improving overall performance and responsiveness for end-users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Off-Chain Indexing
&lt;/h3&gt;

&lt;p&gt;Implementing off-chain indexing in Substrate involves defining what data to index and where to store it. Substrate provides a local storage API within the runtime that can be used for this purpose. When a relevant on-chain event occurs or a specific state transition happens, the runtime logic can extract the necessary information and use the &lt;code&gt;offchain::local_storage_set&lt;/code&gt; function to store it under a specific key in the node's local storage. It's crucial to design a well-structured key-value system for efficient retrieval.&lt;/p&gt;

&lt;p&gt;Let's say we want to index transfer events in a simple token pallet. When a &lt;code&gt;Transfer&lt;/code&gt; event is emitted, the runtime can extract the &lt;code&gt;from&lt;/code&gt;, &lt;code&gt;to&lt;/code&gt;, and &lt;code&gt;value&lt;/code&gt; and store this information off-chain using a composite key like (&lt;code&gt;block_number&lt;/code&gt;, &lt;code&gt;event_index&lt;/code&gt;) or a key based on the to address for quick balance lookups. An Offchain Worker could then periodically aggregate these off-chain transfer records to calculate user balances or generate transaction history summaries. The following snippet illustrates a simplified example within a Substrate pallet's &lt;code&gt;on_finalize&lt;/code&gt; hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#![cfg_attr(not(feature&lt;/span&gt; &lt;span class="nd"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"std"&lt;/span&gt;&lt;span class="nd"&gt;),&lt;/span&gt; &lt;span class="nd"&gt;no_std)]&lt;/span&gt;

&lt;span class="c1"&gt;// Import necessary modules and traits from the frame_support and frame_system crates.&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;frame_support&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;
    &lt;span class="n"&gt;decl_module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decl_storage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decl_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decl_error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nn"&gt;traits&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ExistenceRequirement&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;frame_system&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;ensure_signed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;offchain&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;StorageKind&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// Import StorageKind for off-chain storage.&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;sp_std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;prelude&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="c1"&gt;// Import standard library prelude for common types like Vec.&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;codec&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;Decode&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// Import Encode and Decode for serializing and deserializing data.&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Define a module for unit tests.&lt;/span&gt;

&lt;span class="nd"&gt;#[cfg(test)]&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Define a module containing the test cases.&lt;/span&gt;

&lt;span class="c1"&gt;// Define the Trait for this pallet. It specifies the types this pallet depends on.&lt;/span&gt;
&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Trait&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;frame_system&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Trait&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;'static&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Define the Event type for this pallet. It must be convertible to the frame_system's Event type.&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;From&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Into&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;frame_system&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Trait&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;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// Define the Currency type used for token transfers.&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Currency&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AccountId&lt;/span&gt;&lt;span class="o"&gt;&amp;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;// Declare the events that this pallet can emit.&lt;/span&gt;
&lt;span class="nd"&gt;decl_event!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt;
        &lt;span class="n"&gt;AccountId&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;T&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;frame_system&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Trait&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;AccountId&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;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Trait&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Currency&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="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Event emitted when a successful transfer occurs.&lt;/span&gt;
        &lt;span class="nf"&gt;Transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AccountId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AccountId&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Declare the errors that this pallet can return during dispatchable calls.&lt;/span&gt;
&lt;span class="nd"&gt;decl_error!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Trait&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Error returned when the sender has insufficient balance.&lt;/span&gt;
        &lt;span class="n"&gt;InsufficientBalance&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;// Declare the storage items for this pallet.&lt;/span&gt;
&lt;span class="nd"&gt;decl_storage!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Store&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Trait&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Example&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// A simple storage item to hold an optional u32 value.&lt;/span&gt;
        &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="n"&gt;Something&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;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="c1"&gt;// Declare the module logic.&lt;/span&gt;
&lt;span class="nd"&gt;decl_module!&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Trait&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;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Define the error type for this module.&lt;/span&gt;
        &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Define the deposit event function used to emit events.&lt;/span&gt;
        &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;deposit_event&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;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;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// A dispatchable function for transferring tokens.&lt;/span&gt;
        &lt;span class="nd"&gt;#[pallet::weight(&lt;/span&gt;&lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="nd"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origin&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="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AccountId&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="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Currency&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="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nn"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DispatchResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Ensure that the caller of this function is a signed account.&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ensure_signed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;origin&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="c1"&gt;// Get the free balance of the sender.&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;free_balance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Ensure that the sender has enough balance to make the transfer.&lt;/span&gt;
            &lt;span class="nd"&gt;ensure!&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="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Error&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;T&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;InsufficientBalance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// Perform the token transfer.&lt;/span&gt;
            &lt;span class="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Currency&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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="nn"&gt;ExistenceRequirement&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;KeepAlive&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="c1"&gt;// Emit a Transfer event.&lt;/span&gt;
            &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;deposit_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&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;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

            &lt;span class="c1"&gt;// Return Ok to indicate success.&lt;/span&gt;
            &lt;span class="nf"&gt;Ok&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 on_finalize hook is called at the end of each block.&lt;/span&gt;
        &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;on_finalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BlockNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Get the list of events that occurred in the current block.&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;frame_system&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Module&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;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;events&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.last&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// Match on the last event to see if it's a Transfer event.&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nn"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&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;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;last_event&lt;/span&gt;&lt;span class="py"&gt;.event&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// Create a unique key for storing the transfer information off-chain.&lt;/span&gt;
                    &lt;span class="c1"&gt;// The key includes the event name, block number, and event index in the block.&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"transfer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;frame_system&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Module&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;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;event_count&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="nf"&gt;.encode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="c1"&gt;// Encode the transfer information (from, to, value) to be stored.&lt;/span&gt;
                    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;value_to_store&lt;/span&gt; &lt;span class="o"&gt;=&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;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.encode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="c1"&gt;// Store the encoded transfer information in the node's local off-chain storage.&lt;/span&gt;
                    &lt;span class="c1"&gt;// StorageKind::PERSISTENT ensures the data persists across node restarts.&lt;/span&gt;
                    &lt;span class="nn"&gt;sp_io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;offchain&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;local_storage_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;StorageKind&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PERSISTENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;value_to_store&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="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;This direct integration within the runtime ensures that the off-chain index is updated atomically with on-chain state changes. By carefully choosing the data to index and designing an efficient key structure, developers can create highly optimized data access layers for their applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing and Utilizing Off-Chain Indexed Data
&lt;/h2&gt;

&lt;p&gt;Data stored via off-chain indexing using &lt;code&gt;local_storage_set&lt;/code&gt; can be accessed by Offchain Workers using the &lt;code&gt;offchain::local_storage_get&lt;/code&gt; function. This allows OCWs to perform complex queries or aggregations on the indexed data without burdening the on-chain runtime. Additionally, Substrate provides an RPC endpoint, &lt;code&gt;offchain_localStorageGet&lt;/code&gt;, which allows external clients (like frontend applications) to query this off-chain data directly, bypassing the need to fetch and process numerous on-chain events.&lt;/p&gt;

&lt;p&gt;Continuing the decentralized marketplace example, an off-chain worker could periodically scan the off-chain index of listings, filter them based on certain criteria (e.g., recently expired), and then potentially submit on-chain transactions to update the status of these listings. A frontend application could use the &lt;code&gt;offchain_localStorageGet&lt;/code&gt; RPC to display a paginated and filtered list of active listings to users, providing a much faster and more responsive experience than querying on-chain events directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of an off-chain worker accessing and utilizing off-chain indexed data.&lt;/span&gt;
&lt;span class="c1"&gt;// This code snippet would typically reside within an `impl` block for a pallet&lt;/span&gt;
&lt;span class="c1"&gt;// that has declared an `impl OffchainWorker` trait.&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Trait&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;offchain_worker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;BlockNumber&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 a constant prefix for keys to organize off-chain storage.&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;b"transfer"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Iterate through a range of recent block numbers to retrieve transfer events.&lt;/span&gt;
        &lt;span class="c1"&gt;// This is a simplified example; a more robust approach might involve&lt;/span&gt;
        &lt;span class="c1"&gt;// tracking the last processed block number.&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;bn&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;block_number&lt;/span&gt;&lt;span class="nf"&gt;.saturating_sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;BlockNumber&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;block_number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Iterate through potential event indices within the block.&lt;/span&gt;
            &lt;span class="c1"&gt;// The actual number of events per block can vary.&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Example: Check up to 100 events per block&lt;/span&gt;
                &lt;span class="c1"&gt;// Construct the key to retrieve the off-chain data.&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.encode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                &lt;span class="c1"&gt;// Retrieve the data from the local off-chain storage.&lt;/span&gt;
                &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;sp_io&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;offchain&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;local_storage_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;StorageKind&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PERSISTENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// Decode the retrieved data.&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Ok&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;value&lt;/span&gt;&lt;span class="p"&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="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AccountId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AccountId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;T&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Currency&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;encoded&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="p"&gt;{&lt;/span&gt;
                        &lt;span class="c1"&gt;// Now you can utilize the retrieved transfer information.&lt;/span&gt;
                        &lt;span class="c1"&gt;// For example, you could:&lt;/span&gt;
                        &lt;span class="k"&gt;log&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;info!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OCW: Found off-chain transfer at block {:?}, index {:?}: From {:?}, To {:?}, Value {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;bn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&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;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                        &lt;span class="c1"&gt;// Perform some off-chain computation or aggregation with this data.&lt;/span&gt;
                        &lt;span class="c1"&gt;// For instance, you could track the total value transferred to a specific account off-chain.&lt;/span&gt;
                        &lt;span class="c1"&gt;// (Implementation of such logic is beyond the scope of this example).&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;log&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nd"&gt;warn!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OCW: Failed to decode off-chain transfer data at block {:?}, index {:?}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&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="c1"&gt;// No data found for this key. Continue to the next potential event.&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;// Example of accessing off-chain data via RPC (this wouldn't be inside the OCW itself,&lt;/span&gt;
        &lt;span class="c1"&gt;// but demonstrates how an external client might fetch the data).&lt;/span&gt;
        &lt;span class="c1"&gt;// To enable this, you would need to define custom RPC methods in your runtime API.&lt;/span&gt;
        &lt;span class="c1"&gt;// The client would then call `offchain_localStorageGet` with the appropriate key.&lt;/span&gt;
        &lt;span class="c1"&gt;// For instance:&lt;/span&gt;
        &lt;span class="c1"&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;endraw&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// // In your custom RPC implementation:&lt;/span&gt;
        &lt;span class="c1"&gt;// pub fn get_offchain_transfer(&lt;/span&gt;
        &lt;span class="c1"&gt;//     _at: Option&amp;lt;&amp;lt;Block as BlockT&amp;gt;::Hash&amp;gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;//     block_number: &amp;lt;Block as BlockT&amp;gt;::BlockNumber,&lt;/span&gt;
        &lt;span class="c1"&gt;//     event_index: u32,&lt;/span&gt;
        &lt;span class="c1"&gt;// ) -&amp;gt; Result&amp;lt;Option&amp;lt;Bytes&amp;gt;, sp_rpc::error::Error&amp;gt; {&lt;/span&gt;
        &lt;span class="c1"&gt;//     let key = ("transfer", block_number, event_index).encode();&lt;/span&gt;
        &lt;span class="c1"&gt;//     let result = sp_io::offchain::local_storage_get(StorageKind::PERSISTENT, &amp;amp;key);&lt;/span&gt;
        &lt;span class="c1"&gt;//     Ok(result.map(|v| v.into()))&lt;/span&gt;
        &lt;span class="c1"&gt;// }&lt;/span&gt;
        &lt;span class="c1"&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;raw&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;    // A frontend could then call this RPC method to retrieve the encoded data.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

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


The ability for both off-chain workers and external clients to efficiently access off-chain indexed data unlocks powerful possibilities for building feature-rich and performant decentralized applications. It allows for complex data presentation, real-time analytics, and efficient background processing without impacting the core blockchain's performance.

## Challenges and Solutions

### Challenges
- **Data Consistency**: Ensuring the off-chain index remains consistent with the on-chain state is crucial. If the blockchain experiences a rollback, the off-chain index might become out of sync.

- **Scalability of Local Storage**: Relying solely on individual nodes' local storage might present scalability challenges for very large datasets or high-traffic applications.

- **Query Complexity**: While off-chain indexing improves query speed for predefined indexed fields, complex ad-hoc queries might still require more sophisticated off-chain database solutions.

- **Data Availability**: Data stored off-chain is not inherently replicated across the network in the same way as on-chain data. Ensuring data availability might require additional mechanisms.


### Solutions
- **Event-Driven Updates**: Trigger off-chain index updates directly from on-chain events to maintain near real-time consistency.

- **Periodic Reconciliation**: Implement mechanisms for off-chain workers to periodically verify and reconcile the off-chain index with the on-chain state.

- **External Databases**: For very large datasets or complex querying needs, consider using Offchain Workers to populate and query external databases (e.g., PostgreSQL, Elasticsearch) based on on-chain events.

- **Redundancy and Backups**: Implement strategies for backing up and potentially replicating off-chain indexed data across multiple nodes or using distributed off-chain storage solutions.

### Best Practices
- **Index Relevant Data**: Only index data that is frequently queried or requires optimized retrieval. Avoid indexing everything off-chain.

- **Design Efficient Key Structures**: Choose key structures that allow for fast and targeted lookups.

- **Handle Rollbacks Gracefully**: Implement logic to detect and handle potential inconsistencies due to blockchain rollbacks.

- **Monitor Off-Chain Storage**: Regularly monitor the storage usage of your off-chain index.

- **Consider Data Privacy**: Be mindful of any sensitive data being stored off-chain and implement appropriate security measures.

## Looking Ahead

The integration of off-chain indexing with more sophisticated off-chain computation and [storage solutions](https://github.com/JoshOrndorff/substrate-recipes/blob/master/text/off-chain-workers/storage.md) is likely to evolve. We might see more standardized patterns and libraries emerging to simplify the implementation and management of off-chain indexes.

Exploring decentralized off-chain storage solutions (like [IPFS](https://ipfs.tech/) or [Arweave](https://arweave.org/)) in conjunction with off-chain indexing could provide both performance benefits and enhanced data availability and immutability for the indexed data.

Off-chain indexing will become an increasingly essential tool for building scalable and user-friendly decentralized applications on Substrate. As appchains become more data-intensive, the ability to efficiently manage and query data off-chain will be a key differentiator for successful projects.

## Conclusion

Implementing off-chain indexing in Substrate offers a powerful way to optimize data retrieval and storage by leveraging the node's local storage for frequently queried or derived data. By allowing the runtime to directly write indexed information and enabling Offchain Workers and external clients to efficiently access it, developers can build more performant and scalable blockchain applications.

While off-chain indexing introduces its own set of challenges, the benefits in terms of performance and scalability often outweigh the complexities. Understanding and strategically implementing off-chain indexing is a crucial skill for any Substrate developer looking to build robust and user-friendly decentralized solutions.

## References

- **Polkadot SDK Docs**: [https://docs.polkadot.com/develop/parachains/intro-polkadot-sdk/](https://docs.polkadot.com/develop/parachains/intro-polkadot-sdk/).
- **Substrate Recipes: Off-chain Storage**: [https://github.com/JoshOrndorff/substrate-recipes/blob/master/text/off-chain-workers/storage.md](https://github.com/JoshOrndorff/substrate-recipes/blob/master/text/off-chain-workers/storage.md).
- **Substrate Recipes: Off-chain Indexing**: [https://github.com/JoshOrndorff/substrate-recipes/blob/master/text/off-chain-workers/indexing.md](https://github.com/JoshOrndorff/substrate-recipes/blob/master/text/off-chain-workers/indexing.md)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>blockchain</category>
      <category>polkadot</category>
      <category>substrate</category>
    </item>
    <item>
      <title>Installing Elixir on Debian Crostini</title>
      <dc:creator>cyril</dc:creator>
      <pubDate>Sun, 02 Mar 2025 11:49:53 +0000</pubDate>
      <link>https://forem.com/chainparser/installing-elixir-on-debian-crostini-15mk</link>
      <guid>https://forem.com/chainparser/installing-elixir-on-debian-crostini-15mk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;The official Elixir &lt;a href="https://elixir-lang.org/install.html#install-scripts" rel="noopener noreferrer"&gt;installation script&lt;/a&gt; does not support Debian, a flavor of the Linux operating system, that is widely used, specifically in servers, development environments, and Chromebooks.&lt;/p&gt;

&lt;p&gt;In this post, we shall find a workaround and install Elixir on Debian Crostini, a customized version of Debian that comes with ChromeOs which powers Chromebooks worldwide.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://elixir-lang.org/" rel="noopener noreferrer"&gt;Elixir&lt;/a&gt; is a modern functional programming language that runs on &lt;a href="https://www.erlang.org/" rel="noopener noreferrer"&gt;ErlangVM&lt;/a&gt;. It is known for having an easy-to-write syntax, high scalability, and designed to be fault tolerant and scalable. In recent times, Elixir has become the language of choice for managing the systems and logic around AI agents and chatbots due to its concurrency, distributed computing, and real-time capabilities.   &lt;/p&gt;

&lt;p&gt;In the next section, we'll cover the overview of the steps required to install Elixir on Debian systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of Steps
&lt;/h2&gt;

&lt;p&gt;The following steps are required to install Elixir on Debian:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;strong&gt;asdf&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Install Erlang&lt;/li&gt;
&lt;li&gt;Install Elixir&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing ASDF
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://asdf-vm.com/guide/introduction.html" rel="noopener noreferrer"&gt;&lt;strong&gt;asdf&lt;/strong&gt;&lt;/a&gt; is a tool version manager that ensures consistency in the version of tools across users by providing a single interface and configuration file to make development workflows simple.&lt;/p&gt;

&lt;p&gt;To install &lt;code&gt;asdf&lt;/code&gt;, we first need to install dependencies.&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;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; curl git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, clone &lt;code&gt;asdf&lt;/code&gt; from the GitHub repo:&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;$ &lt;/span&gt;git clone https://github.com/asdf-vm/asdf.git ~/.asdf &lt;span class="nt"&gt;--branch&lt;/span&gt; v0.16.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;v0.16.4&lt;/code&gt; with the version of ASDF you wish to install.&lt;/p&gt;

&lt;p&gt;Now let's add the binaries to &lt;code&gt;.bashrc&lt;/code&gt; environment.&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;$ &lt;/span&gt;subl ~/.bashrc 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, you can use any text editor of your choice. This example uses the Sublime Text (&lt;code&gt;subl&lt;/code&gt;) editor.&lt;/p&gt;

&lt;p&gt;Then add the following lines at the end of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;. "$HOME/.asdf/asdf.sh"
. "$HOME/.asdf/completions/asdf.bash"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can fetch the version for &lt;code&gt;asdf&lt;/code&gt; to verify a successful install:&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;$ &lt;/span&gt;asdf &lt;span class="nt"&gt;--version&lt;/span&gt;
v0.15.0-4b9297b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;asdf&lt;/code&gt; installed, we can now proceed to install Erlang.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Erlang
&lt;/h2&gt;

&lt;p&gt;Let's install dependencies before compiling Erlang with &lt;code&gt;asdf&lt;/code&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;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; build-essential autoconf automake m4 libwxgtk3.2-dev libwxgtk-webview3.2-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop libxml2-utils libncurses-dev openjdk-17-jdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then proceed to install Erlang:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ asdf plugin add erlang https://github.com/asdf-vm/asdf-erlang.git
$ asdf install erlang 27.2.4
$ asdf global erlang 27.2.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;27.2.4&lt;/code&gt; is the version of Erlang you wish to install.&lt;/p&gt;

&lt;p&gt;With Erlang installed, we can proceed to finish with adding Elixir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Elixir
&lt;/h2&gt;

&lt;p&gt;Let's add &lt;code&gt;elixir&lt;/code&gt; as a plugin and then execute the install command.&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;$ &lt;/span&gt;asdf plugin add elixir https://github.com/asdf-vm/asdf-elixir.git
&lt;span class="nv"&gt;$ &lt;/span&gt;asdf &lt;span class="nb"&gt;install &lt;/span&gt;elixir 1.18.2-otp-27
&lt;span class="nv"&gt;$ &lt;/span&gt;asdf global elixir 1.18.2-otp-27
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where &lt;code&gt;1.18.2&lt;/code&gt; is the version of &lt;code&gt;elixir&lt;/code&gt;, and &lt;code&gt;27&lt;/code&gt; is the version of Erlang installed beforehand.&lt;/p&gt;

&lt;p&gt;By checking the &lt;code&gt;elixir&lt;/code&gt; version, you should see something similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ elixr -v
Elixir 1.18.2 (compiled with Erlang/OTP 27)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Elixir is now successfully installed. You can now launch the interactive console by executing the following command:&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;$ &lt;/span&gt;iex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, we successfully navigated the challenge of installing Elixir on Debian Crostini, a customized version of Debian used in Chromebooks. By leveraging &lt;strong&gt;asdf&lt;/strong&gt;, a versatile tool version manager, we installed both Erlang and Elixir, ensuring compatibility and consistency. This setup unlocks the power of Elixir’s concurrency, fault tolerance, and real-time capabilities, making it a great choice for building scalable systems, AI agents, and chatbots.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Quantifying LVR on Uniswap v2</title>
      <dc:creator>cyril</dc:creator>
      <pubDate>Thu, 12 Sep 2024 21:51:27 +0000</pubDate>
      <link>https://forem.com/chainparser/quantifying-lvr-on-uniswap-v2-1k1g</link>
      <guid>https://forem.com/chainparser/quantifying-lvr-on-uniswap-v2-1k1g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Did you know that providing liquidity on Uniswap, the most popular decentralized exchange, can lead to systematic underperformance compared to a simple rebalancing strategy? This phenomenon, known as Loss-Versus-Rebalancing (LVR), highlights a hidden cost in liquidity provision that even experienced traders might overlook. LVR occurs due to price slippage when automated market makers (AMMs) like Uniswap execute trades at worse-than-market prices as asset prices fluctuate.&lt;/p&gt;

&lt;p&gt;In this research, we’ll break down the concept of LVR, focusing specifically on its quantification within Uniswap v2. Understanding LVR is crucial for anyone participating in decentralized finance (DeFi) because it directly impacts the returns of liquidity providers (LPs). By exploring how LVR functions and how it can be measured, stakeholders will gain insights into the risks and rewards of liquidity provision, learn strategies to mitigate LVR, and discover how this knowledge can influence AMM design and fee structures in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Objectives
&lt;/h3&gt;

&lt;p&gt;This research aims to achieve the following objectives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quantify and estimate LVR across Ethereum mainnet and major Layer 2 networks (Arbitrum, Optimism, Base).&lt;/li&gt;
&lt;li&gt;Develop a methodology to estimate and compare the Total Addressable Market (TAM) of LVR for Uniswap v2 across different networks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;AMMs like Uniswap, have transformed decentralized exchanges by providing a simpler and more efficient trading mechanism compared to traditional order books used in centralized exchanges. Uniswap v2, for example, operates through a constant function market maker (CFMM) model, relying on passive liquidity providers to facilitate trades.&lt;/p&gt;

&lt;p&gt;LVR is a key concept that measures the performance gap between passive liquidity provision in AMMs and an active rebalancing strategy that adjusts positions based on market prices. This model, inspired by the Black-Scholes framework, focuses on trading between a risky asset and a stable asset, like USDC, with the risky asset's price following a geometric Brownian motion.&lt;/p&gt;

&lt;p&gt;In this model, arbitrageurs exploit price slippage in AMMs, where prices lag behind real-time market movements, leading to LVR. The model assumes an ideal centralized exchange (CEX) with infinite liquidity and no fees for arbitrageurs, ensuring the AMM’s price aligns with the CEX price. It also assumes AMMs follow an invariant curve, maintaining a constant product of reserves.&lt;/p&gt;

&lt;p&gt;The LVR model is influenced by two main factors: the price variance of the risky asset and the available liquidity in the AMM. These factors impact price slippage and the overall losses associated with LVR, offering insights into the economic dynamics of liquidity provision in AMMs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;p&gt;To achieve the objectives of this research, we begin by collecting data on Uniswap v2 pool activity. The data is sourced from the &lt;code&gt;defi.ez_dex_swaps&lt;/code&gt; table on Flipside Crypto, which provides comprehensive trade information, including block timestamp, pool name, pool address, amount in, and amount out. We filter this data specifically for Uniswap v2 trades to ensure relevance to our analysis.&lt;/p&gt;

&lt;p&gt;Given that LVR is calculated based on the volatility between a risky asset and a numeraire (such as USDC, USDT, or DAI), we focus on trades where the output token is one of these stablecoins. This allows us to accurately assess the volatility required for the LVR calculation. By using the &lt;code&gt;amount_in&lt;/code&gt; and &lt;code&gt;amount_out&lt;/code&gt; fields, we can determine the minimum and maximum &lt;strong&gt;effective prices&lt;/strong&gt; for each pool daily. These prices reflect the extreme values at which assets were traded within a pool on a given day.&lt;/p&gt;

&lt;p&gt;The following SQL query is used to generate the necessary dataset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt;
  &lt;span class="n"&gt;date_trunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'day'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block_timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;pool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;contract_address&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pool_addr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount_out&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;amount_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;min_ep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount_out&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;amount_in&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;max_ep&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;defi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ez_dex_swaps&lt;/span&gt;
&lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'uniswap-v2'&lt;/span&gt;
  &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'&lt;/span&gt; &lt;span class="c1"&gt;-- USDC &lt;/span&gt;
    &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="n"&gt;token_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'0xdac17f958d2ee523a2206206994597c13d831ec7'&lt;/span&gt; &lt;span class="c1"&gt;-- USDT&lt;/span&gt;
    &lt;span class="k"&gt;or&lt;/span&gt; &lt;span class="n"&gt;token_out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'0x6b175474e89094c44da98b954eedeac495271d0f'&lt;/span&gt; &lt;span class="c1"&gt;-- DAI&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pool_addr&lt;/span&gt;
&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query is adapted for each network—Ethereum, Arbitrum, Optimism, and Base—by replacing the network name and relevant contract addresses for the numeraires. While this method does not capture 100% of the trades within each pool, it is sufficient for our purposes, assuming the presence of arbitrageurs who ensure price accuracy. This approach is favored for its simplicity and effectiveness in generalizing pool behavior.&lt;/p&gt;

&lt;p&gt;Once we have the daily minimum and maximum effective prices, we calculate the daily volatility as the percentage difference between these two extremes, similar to Today's True Range (TTR) formula. This daily volatility value is then used to compute the LVR. This calculation enables us to quantify LVR across different networks and draw meaningful comparisons.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  LVR on Mainnet
&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%2Fj7klqq37pxbhpuij7fi5.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%2Fj7klqq37pxbhpuij7fi5.png" alt="Mainnet Overall Average LVR - Daily, Weekly, Monthly" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LVR remains consistently high across different time frames for Uniswap v2 pools on Ethereum Mainnet. The weekly average LVR is highest at about 110 basis points, followed closely by monthly and daily averages. The small variation between time frames (only about 10 basis points difference) indicates that LVR is a persistent issue rather than a short-term anomaly. Overall, the data suggests that liquidity providers consistently underperform compared to optimal rebalancing strategies, regardless of the time frame considered.&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%2Fbh91uiwvqjrxoql7pbcv.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%2Fbh91uiwvqjrxoql7pbcv.png" alt="Mainnet Average Daily LVR of 10 Longest Active Pools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is significant variation in LVR across Uniswap v2 pools on Ethereum Mainnet. The DAI-WETH pool stands out with the highest average daily LVR of nearly 200 basis points, indicating substantial underperformance compared to optimal rebalancing. LVR decreases sharply for other pools, with stablecoin pairs and those involving wrapped Bitcoin generally showing lower LVRs. This suggests that pool composition and asset volatility play crucial roles in determining LVR, with some pools performing much closer to optimal strategies than others.&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%2Fi4aue0z9qxmgq4safl7g.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%2Fi4aue0z9qxmgq4safl7g.png" alt="Mainnet Overall Average Daily LVR Over Time" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LVR was extremely high in early 2020, with significant volatility. The LVR spiked above 1,500 basis points at certain points, reflecting a period of heightened market inefficiency and higher costs for liquidity providers. After mid-2020, the LVR declined and stabilized to much lower levels, mostly below 250 basis points, indicating that over time, market conditions on Ethereum Mainnet became more efficient, with LVR settling into a more predictable range.&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%2Frqvtgd6wbu3f55lblwo8.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%2Frqvtgd6wbu3f55lblwo8.png" alt="Mainnet Average LVR by Day of Week" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LVR is relatively stable from Monday to Thursday, staying around 100 basis points. However, it slightly decreases on Friday and continues to drop through Saturday and Sunday. This indicates that liquidity provision might be more favorable over the weekend, possibly because of lower trading volumes or market activity, leading to less slippage and reduced losses from rebalancing inefficiencies.&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%2F5knna6jgr4c5lpa8b7nx.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%2F5knna6jgr4c5lpa8b7nx.png" alt="Mainnet Average LVR by Week of Month" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LVR remains relatively consistent throughout the first four weeks of the month, fluctuating between 90 and 105 basis points. However, the fifth week exhibits a significant increase in LVR, rising to approximately 115 basis points. This suggests that during months with a fifth week, liquidity provision might become less efficient or more costly, potentially due to market conditions that occur towards the end of the month.&lt;/p&gt;

&lt;h3&gt;
  
  
  LVR on Arbitrum
&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%2Fzy7ogwlkqbggy4bkvloi.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%2Fzy7ogwlkqbggy4bkvloi.png" alt="Arbitrum Overall Average LVR Daily, Weekly, Monthly" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Weekly LVR is highest at about 155 basis points, followed closely by monthly LVR at around 150 basis points. Daily LVR is notably lower at approximately 125 basis points. This suggests that losses compared to optimal rebalancing strategies tend to accumulate over longer periods on Arbitrum, with weekly and monthly holdings experiencing higher relative losses than daily positions. &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%2Frdkym91xzu0dwcu0ei0a.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%2Frdkym91xzu0dwcu0ei0a.png" alt="Arbitrum Average Daily LVR of 10 Longest Active Pools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The WETH-DAI pool shows the highest LVR at about 115 basis points, significantly higher than other pools. There's a clear descending trend in LVR as we move through the pools, with stablecoin pairs (USDC-USDT, WBTC-USDC) showing very low LVRs below 5 basis points. This indicates that certain asset pairs, particularly those involving more volatile cryptocurrencies, tend to underperform compared to optimal rebalancing strategies, while stablecoin pairs perform much closer to optimal.&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%2Fxtfor2quwq2ss7lm1co8.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%2Fxtfor2quwq2ss7lm1co8.png" alt="Arbitrum Overall Average Daily LVR Over Time" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's high volatility in LVR, with extreme spikes reaching over 2000 basis points in early March. However, the general trend shows a decrease in LVR over time, with more recent months exhibiting lower and more stable LVR values, mostly below 500 basis points. This suggests an improvement in pool efficiency or liquidity provider strategies on Arbitrum over the observed period.&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%2Fayg0c6fcagztga7cjwzr.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%2Fayg0c6fcagztga7cjwzr.png" alt="Arbitrum Average LVR by Day of Week" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thursday stands out with the highest LVR at nearly 200 basis points, indicating significantly higher losses compared to optimal rebalancing on this day. Tuesday and Sunday also show elevated LVRs above 125 basis points. In contrast, Friday has the lowest LVR at about 85 basis points, followed closely by Monday. This pattern suggests that liquidity providers might benefit from adjusting their strategies based on the day of the week, potentially focusing on rebalancing towards the end of the work week.&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%2Fcfbpby4m7dk1t4gez10u.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%2Fcfbpby4m7dk1t4gez10u.png" alt="Arbitrum Average LVR by Week of Month" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a significant variation in the average Loss-Versus-Rebalancing (LVR) for Uniswap v2 pools on Arbitrum across different weeks of the month, with Week 2 showing the highest LVR at about 160 basis points, followed by Week 3 at around 145 basis points. Week 4 has the lowest LVR at approximately 85 basis points. This suggests that liquidity providers may experience higher losses compared to optimal rebalancing strategies in the middle of the month, while the end of the month tends to see better performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  LVR on Optimism
&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%2Fcjyalpphlkyw1bb07b5s.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%2Fcjyalpphlkyw1bb07b5s.png" alt="Optimism Overall Average LVR Daily, Weekly, Monthly" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Weekly LVR is highest at about 65 basis points, followed by monthly LVR at around 45 basis points. Daily LVR is notably lower at approximately 21 basis points. This suggests that losses compared to optimal rebalancing strategies tend to accumulate over longer periods on Optimism, with weekly and monthly holdings experiencing higher relative losses than daily positions. The significant difference between time frames indicates that the frequency of rebalancing can have a material impact on the performance of liquidity providers on Optimism.&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%2Fcybdwvp59qe5qfy5q68l.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%2Fcybdwvp59qe5qfy5q68l.png" alt="Optimism Average Daily LVR of 10 Longest Active Pools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The USDC-sOPWETH pool shows the highest LVR at about 155 basis points, significantly higher than other pools. The WETH-USDT pool follows with around 70 basis points. There's a sharp decline in LVR for subsequent pools, with the last five pools all showing LVRs below 5 basis points. This indicates that certain asset pairs, particularly those involving wrapped ETH or stablecoins, tend to underperform compared to optimal rebalancing strategies, while other pairs perform much closer to optimal.&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%2Faoeuswjtn87vfiunplne.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%2Faoeuswjtn87vfiunplne.png" alt="Optimism Overall Average Daily LVR Over Time" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The chart shows high volatility, with extreme spikes reaching over 2500 basis points in early March and around 1500 basis points in early May. However, the general trend shows a decrease in LVR over time, with more recent months exhibiting lower and more stable LVR values, mostly below 500 basis points. This suggests an improvement in pool efficiency or liquidity provider strategies on Optimism over the observed period, with occasional periods of high volatility.&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%2Fszgc7o77c9p2kjtjx4af.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%2Fszgc7o77c9p2kjtjx4af.png" alt="Optimism Average LVR by Day of Week" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wednesday shows the highest LVR at nearly 55 basis points, followed by Monday at about 40 basis points and Thursday at around 35 basis points. The weekend days (Saturday and Sunday) and Tuesday have the lowest LVRs, all below 5 basis points. This pattern indicates that liquidity providers on Optimism might benefit from adjusting their strategies based on the day of the week, with mid-week days, especially Wednesday, showing higher potential for losses compared to optimal rebalancing.&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%2Fppfdp1523iy1931z73p0.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%2Fppfdp1523iy1931z73p0.png" alt="Optimism Average LVR by Week of Month" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Week 3 stands out with the highest LVR at about 52 basis points, significantly higher than other weeks. Week 2 follows with around 21 basis points, while Weeks 1 and 5 show similar LVRs of about 12-13 basis points. Week 4 has the lowest LVR at approximately 4 basis points. This pattern suggests that liquidity providers on Optimism may experience higher losses compared to optimal rebalancing strategies in the middle of the month, particularly in Week 3, while the end of the month tends to see better performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  LVR on Base
&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%2Fhh69xhk4m2a7mzkle3aq.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%2Fhh69xhk4m2a7mzkle3aq.png" alt="Base Overall Average LVR Daily, Weekly, Monthly" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Weekly LVR is highest at about 380 basis points, followed by monthly at around 320 basis points, and daily at approximately 260 basis points. Longer time frames (weekly and monthly) show higher average LVRs compared to daily, suggesting that the cumulative effect of price movements and trading activity over extended periods leads to greater divergence from optimal rebalancing.&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%2Fg08gqbsf3je2lbw7wivo.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%2Fg08gqbsf3je2lbw7wivo.png" alt="Base Average Daily LVR of 10 Longest Active Pools" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The WETH-DAI pool has the highest average LVR at about 500 basis points, while the USDCL-swing pool has the lowest at nearly 0 basis points. There's a steep decline in LVR from the top pools to the bottom ones. Pools involving major assets like WETH, DAI, and USDC tend to have higher LVRs, possibly due to higher trading volumes or more significant price movements in these pairs.&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%2F0gz3kamvt2sv6c78lbrd.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%2F0gz3kamvt2sv6c78lbrd.png" alt="Base Overall Average Daily LVR Over Time" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This time series chart shows the daily average LVR from March to September 2024. There's a significant spike in LVR during late March and early April, reaching peaks above 4000 basis points. After this initial period of high volatility, the LVR generally stabilizes at much lower levels, mostly below 1000 basis points, with occasional smaller spikes.&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%2Fj4gjctn6scnguc7ghvvm.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%2Fj4gjctn6scnguc7ghvvm.png" alt="Base Average LVR by Day of Week" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This chart displays the average LVR for each day of the week. Saturday shows the highest average LVR at approximately 320 basis points, while Tuesday has the lowest at about 220 basis points. There's a general upward trend from Tuesday to Saturday, with a sharp decline on Sunday. Weekend trading, particularly on Saturdays, results in higher LVR for Uniswap v2 pools on Base, possibly due to increased volatility or reduced liquidity during these periods.&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%2Fqtxyuap5fdp4z7ixkojl.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%2Fqtxyuap5fdp4z7ixkojl.png" alt="Base Average LVR by Week of Month" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Week 3 has the highest average LVR at around 300 basis points, while Week 1 has the lowest at about 200 basis points. There's a general trend of increasing LVR from Week 1 to Week 3, followed by a decline in Weeks 4 and 5.&lt;/p&gt;

&lt;h3&gt;
  
  
  Total Addressable Market
&lt;/h3&gt;

&lt;p&gt;Total Addressable Market (TAM) in the context of Loss-Versus-Rebalancing (LVR) for Uniswap v2 represents the potential market size for passive liquidity provision across different blockchain networks. LVR is a crucial metric that measures the efficiency of automated market makers (AMMs) compared to active rebalancing strategies.&lt;/p&gt;

&lt;p&gt;To estimate the TAM of LVR for Uniswap v2, we developed a model that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collects historical trading data from Uniswap v2 on each network (Ethereum mainnet, Arbitrum, Optimism, and Base).&lt;/li&gt;
&lt;li&gt;Calculates daily trading volumes for each network.&lt;/li&gt;
&lt;li&gt;Estimates the potential losses liquidity providers (LPs) might incur due to LVR based on price volatility.&lt;/li&gt;
&lt;li&gt;Aggregates this data to determine the average daily TAM for each network and the total across all networks.&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%2Fbsep0i0zase5yvg0gfsq.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%2Fbsep0i0zase5yvg0gfsq.png" alt="Average Daily TAM by Network" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Arbitrum (Average daily TAM: $11.15 million):&lt;br&gt;
The highest TAM suggests that Arbitrum has the most active Uniswap v2 ecosystem among the studied networks. This could indicate higher trading volumes and/or greater price volatility on this network. For LPs, this represents both the largest opportunity and the highest risk of impermanent loss.&lt;/p&gt;

&lt;p&gt;Base (Average daily TAM: $10.37 million):&lt;br&gt;
Close to Arbitrum's value, indicating strong adoption of Uniswap v2 on this newer Layer 2 solution. The high TAM suggests significant LP activity and potential for LVR.&lt;/p&gt;

&lt;p&gt;Ethereum mainnet (Average daily TAM: $10.31 million):&lt;br&gt;
Despite high gas fees, mainnet still shows a substantial TAM, reflecting its established ecosystem and possibly higher-value trades.&lt;/p&gt;

&lt;p&gt;Optimism (Average daily TAM: $0.22 million):&lt;br&gt;
Significantly lower than other networks, suggesting less Uniswap v2 activity or lower price volatility on Optimism. This could mean lower risk for LPs, but also lower potential returns.&lt;/p&gt;

&lt;p&gt;Total average daily TAM ($32.06 million):&lt;br&gt;
This substantial figure across all networks underscores the significant role of AMMs in the DeFi ecosystem and the scale of potential LVR.&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%2Fi93tjiwisgxv2pxv6i5y.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%2Fi93tjiwisgxv2pxv6i5y.png" alt="TAM of All Networks Over Time" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Given the high TAM values, especially on Arbitrum, Base, and mainnet, LPs are likely experiencing significant LVR. However, this doesn't necessarily mean they're losing money overall. In periods of high volatility and trading volume, fees earned might outweigh LVR. Conversely, in less active periods, LVR could exceed fee income.&lt;/p&gt;

&lt;p&gt;The relatively low TAM on Optimism suggests LPs there might be experiencing less LVR, but potentially earning lower fees as well.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This comprehensive analysis of LVR across Uniswap v2 pools on Ethereum mainnet, Arbitrum, Optimism, and Base networks provides valuable insights into the performance of liquidity provision in decentralized finance. The research reveals significant variations in LVR across different networks, time frames, and specific pools. These findings underscore the importance of understanding LVR for liquidity providers, as it directly impacts their returns and can lead to systematic underperformance compared to optimal rebalancing strategies.&lt;/p&gt;

&lt;p&gt;The Total Addressable Market (TAM) analysis further emphasizes the scale and significance of LVR in the DeFi ecosystem. With a total average daily TAM of $32.06 million across all studied networks, it's clear that LVR represents a substantial economic factor in automated market maker (AMM) dynamics. The varying TAM values across networks, with Arbitrum leading at $11.15 million and Optimism trailing at $0.22 million, highlight the differences in market activity and potential risks and opportunities for liquidity providers on each platform.&lt;/p&gt;

&lt;p&gt;As the DeFi landscape continues to evolve, this research serves as a crucial resource for stakeholders to make informed decisions about liquidity provision strategies. The insights gained from this study can guide the development of more efficient AMM designs, help liquidity providers optimize their strategies to mitigate LVR and inform the broader community about the hidden costs associated with passive liquidity provision. Future research could explore how these findings translate to newer AMM models and investigate strategies to minimize LVR while maximizing returns for liquidity providers.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sources&lt;/strong&gt;: &lt;a href="https://arxiv.org/pdf/2208.06046" rel="noopener noreferrer"&gt;https://arxiv.org/pdf/2208.06046&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dataset, Code, and Charts&lt;/strong&gt;: &lt;a href="https://github.com/polymawutor/lvr-uniswapv2" rel="noopener noreferrer"&gt;https://github.com/polymawutor/lvr-uniswapv2&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;mawutor (&lt;a href="https://x.com/polymawutor" rel="noopener noreferrer"&gt;@polymawutor&lt;/a&gt;) is a web3 developer with a passion for exploring the latest advancements in blockchain technology. With a focus on providing informative content and building innovative solutions, mawutor aims to demystify complex topics and empower users with actionable insights.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>KAIA Tokenomics Explained</title>
      <dc:creator>cyril</dc:creator>
      <pubDate>Wed, 21 Aug 2024 10:26:43 +0000</pubDate>
      <link>https://forem.com/chainparser/kaia-tokenomics-explained-1dog</link>
      <guid>https://forem.com/chainparser/kaia-tokenomics-explained-1dog</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Did you know &lt;a href="https://www.kaia.io/" rel="noopener noreferrer"&gt;Kaia Chain's&lt;/a&gt; token economy (tokenomics) is designed to mint approximately 200 million tokens annually? This amounts to a controlled 5.2% annual inflation rate strategically managed to fuel growth and investment in the network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://coinmarketcap.com/currencies/klaytn/" rel="noopener noreferrer"&gt;KAIA&lt;/a&gt; is the primary cryptocurrency within the Kaia ecosystem. It is used to pay transaction fees associated with creating or executing smart contracts and transferring KAIA tokens.&lt;/p&gt;

&lt;p&gt;KAIA's tokenomics is designed as more than just a reward system for validators; it's a comprehensive strategy for sustainable growth and long-term investment. Unlike Bitcoin and Ethereum which only focus on technical maintenance through token rewards, Kaia's economy also incentivizes contributions from a broader range of participants.  &lt;/p&gt;

&lt;p&gt;Kaia's blockchain technology is designed for enterprise adoption, therefore, it is crucial to understand how the network balances the needs of validators, ecosystem growth, and infrastructure development. &lt;/p&gt;

&lt;p&gt;In this post, we will learn about Kaia's token economy which continuously supports the network growth through block rewards, making it a resilient and future-focused chain. The end goal is to deepen our understanding of Kaia and how the chain sustains the ecosystem and drives innovation. &lt;/p&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Blockchain technology has revolutionized the way we think about finance, digital assets, and decentralized networks. At the heart of many blockchains lies a "token economy," a system designed to incentivize network participants and ensure the network's health, security, and growth. Understanding this concept and related terms like inflation and circulating supply is crucial to grasping how a blockchain project like Kaia operates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Concepts Explained
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Token Economy
&lt;/h4&gt;

&lt;p&gt;A token economy refers to the ecosystem of a blockchain where tokens are used as a means of incentivizing participants, conducting transactions, and governing the network. In many cases, these tokens are created, distributed, and managed according to rules defined by the network's protocol. The token economy is crucial because it determines how resources are allocated, how security is maintained, and how growth and innovation are incentivized.&lt;/p&gt;

&lt;h4&gt;
  
  
  Inflation
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.imf.org/en/Publications/fandd/issues/Series/Back-to-Basics/Inflation#:~:text=Inflation%20is%20the%20rate%20of,of%20living%20in%20a%20country." rel="noopener noreferrer"&gt;Inflation&lt;/a&gt; in the context of a blockchain refers to the rate at which new tokens are created and added to the existing supply. This is similar to traditional economic inflation, where the supply of money in an economy increases. Inflation is often used in blockchains to reward participants, such as validators or miners, who contribute to the network's maintenance and security. However, if not managed carefully, it can lead to a dilution of the token's value.&lt;/p&gt;

&lt;h4&gt;
  
  
  Circulating Supply
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://www.meetbunch.com/terms/circulating-supply" rel="noopener noreferrer"&gt;circulating supply&lt;/a&gt; of a token is the total amount of that token currently available and being actively traded or used in the market. It excludes tokens that are locked, reserved, or otherwise not in circulation. The circulating supply is a key metric for understanding the token's market dynamics, including its price and overall market capitalization.&lt;/p&gt;

&lt;h4&gt;
  
  
  Block Reward
&lt;/h4&gt;

&lt;p&gt;Block rewards are the incentives given to miners or validators for adding a new block of transactions to the blockchain. These rewards typically consist of newly minted tokens (inflationary rewards) and transaction fees from the transactions included in the block.&lt;/p&gt;

&lt;h4&gt;
  
  
  Staking
&lt;/h4&gt;

&lt;p&gt;Staking is the process of locking up tokens in a blockchain network to support its operations, like validating transactions and securing the network. In return, participants (called validators or stakers) earn rewards, often in the form of additional tokens.&lt;/p&gt;

&lt;p&gt;In the following sections, we shall deep dive into Kaia's token economy functions and why it's an integral part of an overarching strategy for sustainable growth and innovation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep Dive
&lt;/h2&gt;

&lt;p&gt;Kaia's funding structure is tied to generating new blocks in its network. A "block reward" consisting of newly issued KAIA tokens and transaction fees is distributed for each new block (~1s). The rewards are allocated as follows: 50% goes to validators and the community, 25% to the Kaia Ecosystem Fund (KEF), and 25% to the Kaia Infrastructure Fund (KIF). Of the 50% designated for validators and the community, 20% (or 10% of the total) is given as block proposer rewards, while 80% (or 40% of the total) is for staking rewards. Kaia mints 6.4 KAIA tokens per block, resulting in about 200 million new tokens annually, with an annual inflation rate of approximately 5.2%. Transaction fees are applied according to predetermined fee tables.&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%2Fg6h7znxnbfbce3eibegv.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%2Fg6h7znxnbfbce3eibegv.png" alt="Kaia's Funding Structure" width="600" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Cell Operators &amp;amp; The Staking Community
&lt;/h3&gt;

&lt;p&gt;In Kaia, Core Cell Operators (CCOs), who make up the Kaia Governance Council, play a crucial role in maintaining the network's infrastructure. To become a member of this council, candidates must pass a qualification review and stake a minimum of 5 million KAIA tokens.&lt;/p&gt;

&lt;h4&gt;
  
  
  Reward Mechanism
&lt;/h4&gt;

&lt;p&gt;For each new block, a Committee is &lt;a href="https://dev.to/polymawutor/deep-dive-into-the-consensus-mechanism-of-kaia-chain-11j7#:~:text=Election%20of%20A%20Committee%3A%20VRF%20In%20Action"&gt;randomly formed&lt;/a&gt; from the Kaia Governance Council. This Committee consists of one member who acts as the Proposer and others who serve as Validators. Once a block is successfully added to the blockchain, the block reward is distributed as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Proposer Reward: The Proposer, who is randomly selected, receives 10% of the block reward. This reward is evenly distributed among all Council members over time, ensuring that each has an equal opportunity to benefit from this role.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Staking Rewards: The remaining 40% of block rewards allocated to the Council (and staking community) are distributed based on the amount of KAIA staked by each member. Only the amount staked beyond the minimum 5 million KAIA requirement is considered for this proportional distribution. Members who stake more KAIA receive a larger share of these rewards, encouraging them to commit more resources to the network.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Council members can adjust their staking amounts freely, as long as they meet the minimum requirement. Staking data is updated every 86,400 blocks, with newly staked tokens becoming active two update cycles later. Unstaking requires a one-week delay, which helps prevent any sudden exits from the network by malicious actors.&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%2F388r1r27eu209m4lw4ns.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%2F388r1r27eu209m4lw4ns.png" alt="Kaia Block Rewards Structure" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Kaia Ecosystem Fund (KEF)
&lt;/h3&gt;

&lt;p&gt;The Kaia Ecosystem Fund (KEF) is a crucial component of Kaia’s mission to enhance transparency and verifiability within its ecosystem. Funded by 25% of the total KAIA tokens issued with each new block, the KEF is dedicated to activities that bolster the Kaia network’s growth and sustainability.&lt;/p&gt;

&lt;h4&gt;
  
  
  Key Areas of KEF Utilization
&lt;/h4&gt;

&lt;p&gt;The Kaia Ecosystem Fund (KEF) plays a vital role in incentivizing contributions to the Kaia network. It rewards developers and users who enhance the ecosystem's value and functionality through the Service Contribution Reward (SCR) program. This ensures that those who actively contribute to the network are recognized and encouraged to continue their efforts.&lt;/p&gt;

&lt;p&gt;In addition to rewards, the KEF invests in building and strengthening the Kaia developer community. This includes supporting hackathons, educational programs, and collaborations with academic institutions and decentralized autonomous organizations (DAOs). These initiatives aim to foster innovation and attract talent to the Kaia ecosystem.&lt;/p&gt;

&lt;p&gt;The KEF also funds the development of essential infrastructure and services, ensuring that projects with clear utility receive the necessary support. This includes both financial backing and marketing efforts to promote these services within the ecosystem.&lt;/p&gt;

&lt;p&gt;Beyond direct support, the KEF engages in indirect investments through specialized crypto venture capital firms. These strategic investments are designed to generate returns that can be reinvested into the Kaia ecosystem or used to manage the token supply by burning tokens.&lt;/p&gt;

&lt;p&gt;Finally, the KEF allocates resources to support governance committees focused on expanding Kaia's influence in areas like Gaming, DeFi, and Community. It also funds a wide range of activities aimed at nurturing and growing the broader Kaia community.&lt;/p&gt;

&lt;h4&gt;
  
  
  Governance and Administration
&lt;/h4&gt;

&lt;p&gt;The Kaia Governance Council (GC) oversees the administration of the KEF. The Foundation submits a quarterly budget proposal for the fund, which is reviewed and approved by the GC. Specific uses of the funds are also subject to GC approval. &lt;/p&gt;

&lt;p&gt;All fund allocations and expenditures are transparently disclosed to the community, and new proposals for KEF use can be submitted through the GC, requiring individual approval.&lt;/p&gt;




&lt;h3&gt;
  
  
  Kaia Infrustructure Fund
&lt;/h3&gt;

&lt;p&gt;The Kaia Infrastructure Fund (KIF) is a crucial operational fund designed to support the ongoing development and maintenance of Kaia's ecosystem. It is funded by 25% of the total KAIA tokens issued with each new block. The KIF focuses on three main areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Mainnet and Essential Infrastructure R&amp;amp;D: This includes advancing research and development in mainnet technologies, creating foundational services, and establishing critical infrastructure needed for the Kaia network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ecosystem Acceleration: The KIF provides financial support for small-scale partners within the Kaia Blockchain ecosystem, facilitates token swaps, helps attract new members to the Governance Council, and provides market liquidity to enhance the ecosystem’s growth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Foundation Operations: The fund covers operational expenses related to development, accounting, legal affairs, IT infrastructure, marketing, labor costs, and financial management, ensuring the smooth operation of the Kaia Foundation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The KIF is managed by the Kaia Foundation, which establishes and executes budget plans through an internal control system. To ensure transparency, the foundation publicly announces budget plans and execution details before and after fund allocation, providing full disclosure to the community.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenges and Solutions
&lt;/h2&gt;

&lt;p&gt;Kaia's token economy is designed to support a sustainable and adaptable ecosystem, but like any blockchain project, it faces certain challenges. Two significant issues are KAIA token inflation and the need for flexibility and adaptability in managing the token economy.&lt;/p&gt;

&lt;h3&gt;
  
  
  KAIA Token Inflation
&lt;/h3&gt;

&lt;p&gt;One of the primary challenges is managing the inflation rate of KAIA tokens, with 200 million new tokens minted annually. This high inflation rate can increase selling pressure, potentially affecting the token's value in the market. However, Kaia has implemented several solutions to mitigate this issue.&lt;/p&gt;

&lt;p&gt;First, 50% of the new tokens are allocated to the Kaia Ecosystem Fund (KEF) and the Kaia Infrastructure Fund (KIF). These funds are not immediately added to the active circulating supply but are instead held in reserve. They can only be activated through governance proposals, meaning that the tokens do not impact the market unless the community decides to utilize them for specific projects or initiatives. This approach helps manage inflationary effects and reduces immediate sell pressure on the market.&lt;/p&gt;

&lt;p&gt;Additionally, Kaia employs a transaction-based &lt;a href="https://docs.kaia.io/kaiatech/kaia-tokenomics/#burning" rel="noopener noreferrer"&gt;burning mechanism&lt;/a&gt; as part of its strategy to control inflation. A portion of the transaction fees collected within the ecosystem is automatically burned, effectively reducing the circulating supply of KAIA. This burning process is carefully adjusted through consensus among key network participants to balance the reduction in supply with the incentives for node operators. By integrating this burn mechanism, Kaia further mitigates the inflationary pressures and supports the long-term sustainability and value of the KAIA token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexibility and Adaptability of Kaia's Token Economy
&lt;/h3&gt;

&lt;p&gt;Another challenge is ensuring that Kaia's token economy can adapt to the changing needs of the ecosystem and market conditions. To address this, Kaia has introduced a Treasury Rebalance mechanism that allows for adjustments to the allocation of funds within the ecosystem.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.kaia.io/learn/governance/governance-by-kip/#kip-160-an-update-on-treasury-fund-rebalancing-" rel="noopener noreferrer"&gt;Treasury Rebalance Contract&lt;/a&gt; is a smart contract that governs this process transparently and securely. It functions as a finite state machine, progressing through stages of initialization, registration, approval, and finalization. This structured approach ensures that any adjustments to the treasury are thoroughly reviewed and approved by the community.&lt;/p&gt;

&lt;p&gt;Key features of this contract include the ability to adjust the total fund balance, aligning rebalance events with network upgrades, and ensuring transparent execution of the entire process on the blockchain. The rebalance is only executed after consensus is reached among validators, and the details of each event are immutably recorded for future reference and auditing. This mechanism allows Kaia to dynamically respond to the ecosystem's evolving needs while maintaining transparency and security.&lt;/p&gt;

&lt;p&gt;By leveraging these practical solutions, Kaia can effectively manage inflation and maintain a flexible and adaptive token economy, ensuring the long-term stability and growth of its ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;p&gt;Kaia's mainnet, a result of the merger between the &lt;a href="https://klaytn.foundation/" rel="noopener noreferrer"&gt;Klaytn&lt;/a&gt; and &lt;a href="https://www.finschia.io/" rel="noopener noreferrer"&gt;Finschia&lt;/a&gt; ecosystems, &lt;a href="https://x.com/BuildonKaia/status/1825456784322265367" rel="noopener noreferrer"&gt;has yet to be launched&lt;/a&gt;. As KLAY and FNSA merge into KAIA, the token economy will inherit and build upon the foundations of both ecosystems.&lt;/p&gt;

&lt;p&gt;Looking ahead, Kaia's plans for its token economy include expanding participation in the Kaia Ecosystem Fund (KEF) by developing a structure that allows more ecosystem participants to propose and engage in the fund's utilization. For areas that require specialized and rapid decision-making, Kaia is also considering the establishment of separate governance committees. This approach aims to make the token economy more inclusive, flexible, and responsive to the needs of the ecosystem, ensuring that the community can actively contribute to and shape its development.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, Kaia's token economy is meticulously designed to support both immediate and long-term network growth while managing inflation and fostering community involvement. The annual minting of approximately 200 million KAIA tokens, although significant, is carefully controlled through the allocation of 50% of these tokens to the Kaia Ecosystem Fund (KEF) and Kaia Infrastructure Fund (KIF). These tokens are not part of the active supply unless activated by community-driven governance proposals, which helps mitigate potential inflationary pressures on the token's market value.&lt;/p&gt;

&lt;p&gt;Furthermore, the introduction of the Treasury Rebalance mechanism ensures that Kaia's token economy remains adaptable and responsive to evolving market conditions and ecosystem needs. This smart contract-based system enables flexible adjustments to the treasury's fund allocation, ensuring transparency and consensus-driven decision-making. &lt;/p&gt;

&lt;p&gt;As Kaia looks to the future, it plans to enhance the inclusivity and agility of its token economy—through expanded participation in the KEF and the potential establishment of specialized governance committees—and underline its commitment to a sustainable, dynamic, and community-focused ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kaia native coin - KAIA: &lt;a href="https://docs.kaia.io/learn/kaia-native-token/" rel="noopener noreferrer"&gt;https://docs.kaia.io/learn/kaia-native-token/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;KAIA Token Economy: &lt;a href="https://docs.kaia.io/learn/token-economy/" rel="noopener noreferrer"&gt;https://docs.kaia.io/learn/token-economy/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Kaia Ecosystem Overview: &lt;a href="https://flipsidecrypto.xyz/ellerydurwin/kaia-ecosystem-overview-O3VrbJ" rel="noopener noreferrer"&gt;https://flipsidecrypto.xyz/ellerydurwin/kaia-ecosystem-overview-O3VrbJ&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Kaia Blockchain Performance and Consensus Metrics: &lt;a href="https://flipsidecrypto.xyz/jorshimayor/kaia-blockchain-performance-and-consensus-metrics-bCivyK" rel="noopener noreferrer"&gt;https://flipsidecrypto.xyz/jorshimayor/kaia-blockchain-performance-and-consensus-metrics-bCivyK&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;mawutor (&lt;a href="https://x.com/polymawutor" rel="noopener noreferrer"&gt;@polymawutor&lt;/a&gt;) is a web3 developer with a passion for exploring the latest advancements in blockchain technology. With a focus on providing informative content and building innovative solutions, mawutor aims to demystify complex topics and empower users with actionable insights.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Deep Dive Into The Consensus Mechanism of Kaia Chain</title>
      <dc:creator>cyril</dc:creator>
      <pubDate>Wed, 14 Aug 2024 21:32:02 +0000</pubDate>
      <link>https://forem.com/chainparser/deep-dive-into-the-consensus-mechanism-of-kaia-chain-11j7</link>
      <guid>https://forem.com/chainparser/deep-dive-into-the-consensus-mechanism-of-kaia-chain-11j7</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Imagine a blockchain that processes 4,000 transactions per second, with each transaction reaching finality within a second. This isn't a futuristic dream—it's the reality of &lt;a href="https://kaia.io" rel="noopener noreferrer"&gt;Kaia&lt;/a&gt;. In a world where speed, security, and reliability are paramount, Kaia's optimized &lt;a href="https://en.wikipedia.org/wiki/Byzantine_fault" rel="noopener noreferrer"&gt;Istanbul Byzantine Fault Tolerant (BFT)&lt;/a&gt; consensus mechanism is setting new benchmarks.&lt;/p&gt;

&lt;p&gt;This deep dive explores the intricacies of Kaia's consensus mechanism, a system designed not just for blockchain enthusiasts but for enterprises seeking performance and trustworthiness. We'll uncover how Kaia achieves &lt;a href="https://www.nervos.org/knowledge-base/What_is_finality_crypto_(explainCKBot)#:~:text=Instant%20finality%20is%20achieved%20in%20networks%20using%20pBFT%2Dbased%20consensus%2C%20where%20transactions%20are%20confirmed%20immediately%20and%20are%20irreversible.%20Unconditional%20finality%20implies%20absolute%20assurance%20against%20reversal%2C%20requiring%20a%20high%20degree%20of%20network%20centralization%20or%20a%20unique%20consensus%20mechanism." rel="noopener noreferrer"&gt;immediate finality&lt;/a&gt;, why its consensus model matters in the broader blockchain landscape, and what you can expect to learn about the underlying technology powering this innovative network.&lt;/p&gt;

&lt;p&gt;Whether you're a developer, an enterprise leader, or a crypto enthusiast, understanding Kaia's consensus mechanism will provide you with valuable insights into how cutting-edge blockchain technology is being harnessed to meet the demands of tomorrow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;At the heart of any blockchain is its consensus mechanism—a process by which nodes in the network agree on the validity of transactions and the state of the ledger. This mechanism is crucial because it ensures that all participants maintain a synchronized and accurate copy of the blockchain, even in the presence of malicious actors or network failures.&lt;/p&gt;

&lt;h4&gt;
  
  
  Practical Byzantine Fault Tolerance (PBFT)
&lt;/h4&gt;

&lt;p&gt;Kaia employs a variant of the &lt;a href="https://www.geeksforgeeks.org/practical-byzantine-fault-tolerancepbft/" rel="noopener noreferrer"&gt;Practical Byzantine Fault Tolerance (PBFT)&lt;/a&gt; consensus algorithm. PBFT is designed to handle situations where some nodes in the network may act maliciously or fail. The term "Byzantine fault" refers to a situation where components of a system fail and there is imperfect information on whether a component has failed. PBFT ensures that &lt;strong&gt;as long as more than two-thirds of the nodes are functioning correctly, the network can reach a consensus.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The consensus process involves electing a committee, including a proposer and validators. The elected proposer generates a block, which is then verified and signed by the committee. This mechanism allows Kaia to process 4,000 transactions per second with instant finality.&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%2Fkxtereisasysvxtupeeo.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%2Fkxtereisasysvxtupeeo.png" alt="Kaia Consensus" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Election of A Committee: VRF In Action
&lt;/h3&gt;

&lt;p&gt;In Kaia’s consensus mechanism, the election of the committee is a critical process that ensures the blockchain's security, efficiency, and scalability. This process is executed using a &lt;a href="https://en.wikipedia.org/wiki/Verifiable_random_function#:~:text=In%20cryptography%2C%20a%20verifiable%20random,proof%20for%20any%20input%20value." rel="noopener noreferrer"&gt;Verifiable Random Function (VRF)&lt;/a&gt;, a cryptographic tool that plays a vital role in selecting the nodes that participate in block generation and validation.&lt;/p&gt;

&lt;h4&gt;
  
  
  How the VRF Works in Committee Election
&lt;/h4&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%2Fe7ylwdhonhuv3tup8hlr.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%2Fe7ylwdhonhuv3tup8hlr.png" alt="Kaia VRF" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Council Formation
&lt;/h5&gt;

&lt;p&gt;Kaia’s network consists of numerous &lt;a href="https://docs.kaia.io/nodes/" rel="noopener noreferrer"&gt;Consensus Nodes (CNs)&lt;/a&gt;, which collectively form what is known as the Council. The Council is responsible for maintaining the blockchain’s integrity by participating in block generation and validation.&lt;/p&gt;

&lt;h5&gt;
  
  
  Random Selection of Committee
&lt;/h5&gt;

&lt;p&gt;For each block generation round, a subset of the CNs from the Council is selected to form the Committee. The selection is done in a random but deterministic manner, meaning that although the process is random, it can be verified by other nodes in the network to ensure fairness and transparency.&lt;/p&gt;

&lt;h5&gt;
  
  
  Committee’s Role
&lt;/h5&gt;

&lt;p&gt;Once the Committee is selected, these nodes are tasked with proposing and validating the new block. The block proposer is chosen among the Committee members, and the remaining members validate the block by exchanging consensus messages. The VRF ensures that the selection of the Committee is both unpredictable and resistant to manipulation by malicious actors.&lt;/p&gt;

&lt;h4&gt;
  
  
  Significance and Impact of VRF-Based Committee Election
&lt;/h4&gt;

&lt;h5&gt;
  
  
  Scalability
&lt;/h5&gt;

&lt;p&gt;The VRF allows Kaia to efficiently manage a large number of nodes by limiting the number of nodes that participate in the consensus process for each block. By randomly selecting a smaller Committee from a larger pool, Kaia reduces the communication overhead and the complexity of reaching consensus, which is crucial for maintaining high transaction throughput and fast finality.&lt;/p&gt;

&lt;h5&gt;
  
  
  Security and Fairness
&lt;/h5&gt;

&lt;p&gt;The randomness introduced by the VRF makes it extremely difficult for any single entity or group to predict or influence the selection of the Committee. This enhances the security of the network by reducing the risk of targeted attacks on the nodes responsible for block generation.&lt;/p&gt;

&lt;h5&gt;
  
  
  Finality and Performance
&lt;/h5&gt;

&lt;p&gt;Since consensus is reached by a small, dynamically selected group of nodes, the process is swift and efficient, enabling Kaia to achieve immediate finality for each block. This is essential for enterprise-grade applications where delays in transaction confirmation are unacceptable.&lt;/p&gt;

&lt;h5&gt;
  
  
  Communication Efficiency
&lt;/h5&gt;

&lt;p&gt;By limiting consensus communication to only the Committee members, Kaia effectively reduces the communication volume that typically increases in Byzantine Fault Tolerance (BFT) systems as the number of participating nodes grows. This approach helps maintain network performance even as the network scales.&lt;/p&gt;

&lt;p&gt;In the following sections, we shall take a look at how new blocks are proposed and validated by the Committee. &lt;/p&gt;




&lt;h3&gt;
  
  
  Block Generation by Proposer
&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%2Fun84208xnnzqgk6mavih.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%2Fun84208xnnzqgk6mavih.png" alt="Kaia block proposal process" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Proposal Creation
&lt;/h4&gt;

&lt;p&gt;At the beginning of each round, one member of the Committee is chosen as the block proposer. The chosen proposer gathers pending transactions from the transaction pool and compiles them into a new block. The proposer must ensure that the transactions are valid and that they meet the network’s rules (e.g., correct signatures, and sufficient gas fees).&lt;/p&gt;

&lt;p&gt;The proposer then creates a block header that includes essential information such as the block number, timestamp, previous block hash, and a Merkle root of the transactions included in the block.&lt;/p&gt;

&lt;h4&gt;
  
  
  Block Broadcasting
&lt;/h4&gt;

&lt;p&gt;Once the block is created, the proposer broadcasts it to the other Committee members for validation. The broadcasting is done through a dedicated propagation channel for blocks, which helps manage network congestion and ensures that the block is quickly received by all Committee members.&lt;/p&gt;




&lt;h3&gt;
  
  
  Block Verification &amp;amp; Signing by Committee
&lt;/h3&gt;

&lt;p&gt;On Kaia, the process of block verification and signing by the Committee is a crucial step that ensures the integrity, security, and finality of each block added to the blockchain. Here’s a detailed exploration of this process.&lt;/p&gt;

&lt;h4&gt;
  
  
  Block Verification Process
&lt;/h4&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%2Fxdzyjs6zmgygrm57tvwj.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%2Fxdzyjs6zmgygrm57tvwj.png" alt="Kaia block verification" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Integrity Check
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Data Integrity: Each Committee member first verifies the block’s integrity by checking its header and ensuring that the block hasn’t been tampered with. This includes verifying the block’s hash against the cryptographic hash included in the block header.&lt;/li&gt;
&lt;li&gt;Transaction Integrity: Members also verify that all transactions included in the block are valid. This involves checking that transactions have correct signatures, sufficient funds, and adherence to the protocol’s rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Consensus Rules Compliance
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Network Rules: Committee members ensure that the block complies with all network consensus rules. This might include checks for block size limits, transaction limits, and any other protocol-specific rules.&lt;/li&gt;
&lt;li&gt;Previous Block Hash: The block must reference the correct hash of the previous block, ensuring that it fits properly into the blockchain’s existing structure.&lt;/li&gt;
&lt;li&gt;Validation Feedback: If the block passes these checks, Committee members prepare to sign the block. If any issues are detected, the block is rejected, and the proposer may need to create a new block or correct the errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Signature Collection Process
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Signing the Block&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signature Creation: Once a block is validated, each Committee member generates a digital signature for the block. This signature is cryptographic proof that the member has validated the block and agrees with its content.&lt;/li&gt;
&lt;li&gt;Signature Transmission: Each Committee member sends their signature back to the proposer. This is done through secure channels to prevent tampering or interception.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Collecting Signatures&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Threshold Requirement: The proposer collects signatures from the Committee members. For the block to be finalized and added to the blockchain, it must receive signatures from more than &lt;strong&gt;two-thirds&lt;/strong&gt; of the Committee members. This threshold ensures that the block has broad consensus among the Committee members.&lt;/li&gt;
&lt;li&gt;Finalization: Once the proposer has the required number of signatures, the block is finalized. The block is then propagated across the network through a dedicated transaction propagation channel, ensuring that all nodes update their copies of the blockchain.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Kaia’s block verification and signing process leverages a combination of cryptographic techniques and protocol rules to ensure that each block is valid, secure, and quickly finalized. This approach balances the need for high performance with strong security, making Kaia a compelling choice for both decentralized applications and enterprise solutions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenges and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Challenge 1: Network Congestion
&lt;/h3&gt;

&lt;h5&gt;
  
  
  Issue
&lt;/h5&gt;

&lt;p&gt;Kaia’s consensus mechanism, while designed to handle high transaction throughput, can face network congestion during peak periods. This congestion can impact the efficiency of block propagation and transaction validation, leading to delays in finalizing transactions and increased latency.&lt;/p&gt;

&lt;h5&gt;
  
  
  Solution
&lt;/h5&gt;

&lt;p&gt;To mitigate network congestion, Kaia employs a multi-channel approach for block and transaction propagation. Ensuring that these channels are well-optimized and capable of handling high traffic volumes is crucial. Additionally, implementing dynamic load-balancing techniques can help distribute network traffic more evenly. Regular network performance monitoring and scaling the network infrastructure as needed can also alleviate congestion issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 2: Committee Selection Bias
&lt;/h3&gt;

&lt;h5&gt;
  
  
  Issue
&lt;/h5&gt;

&lt;p&gt;Although the VRF is designed to ensure fairness in committee selection, there is a potential risk of selection bias if the VRF implementation is flawed or if there are vulnerabilities in the random number generation process. Such biases could lead to an uneven distribution of power among nodes or reduced security.&lt;/p&gt;

&lt;h5&gt;
  
  
  Solution
&lt;/h5&gt;

&lt;p&gt;Regularly auditing the VRF implementation for vulnerabilities and ensuring its cryptographic robustness is essential. Additionally, incorporating randomness from multiple sources and cross-checking VRF results can enhance fairness. Implementing a transparent process for selecting committee members, with verifiable records, can also help maintain trust in the selection process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenge 3: Scalability with Increasing Node Count
&lt;/h3&gt;

&lt;h5&gt;
  
  
  Issue
&lt;/h5&gt;

&lt;p&gt;As the number of Consensus Nodes in the network grows, the communication volume among nodes can increase, potentially leading to inefficiencies in the consensus process and slower block propagation.&lt;/p&gt;

&lt;h5&gt;
  
  
  Solution
&lt;/h5&gt;

&lt;p&gt;Kaia’s solution to this issue lies in the fixed-size Committee used for block verification and signing. Instead of involving all CNs in the consensus process for each block, Kaia elects a fixed number of Committee members for each round. Hence, increasing the number of CNs does not affect the communication volume among Committee members.&lt;/p&gt;

&lt;p&gt;By addressing these common challenges with practical solutions, Kaia enhances its consensus mechanism's robustness, efficiency, and reliability, ensuring it meets the demands of a growing and dynamic blockchain ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, Kaia employs an advanced consensus mechanism based on an optimized version of Istanbul BFT, which incorporates Practical Byzantine Fault Tolerance (PBFT) with specific modifications for blockchain networks. This approach is designed to provide rapid transaction finality and high throughput, essential for enterprise-grade applications. The consensus process involves a fixed-size Committee elected through a Verifiable Random Function (VRF), which ensures fairness and manages communication volume efficiently.&lt;/p&gt;

&lt;p&gt;In Kaia’s mechanism, block generation begins with a randomly selected proposer from the Committee who creates and broadcasts a block. The block is then validated by the Committee members, who check its integrity and compliance with network rules. Once validated, the Committee members sign the block, and the proposer collects the required signatures from more than two-thirds of the Committee to finalize it. The finalized block is propagated through separate channels for blocks and transactions, optimizing network performance and managing congestion.&lt;/p&gt;

&lt;p&gt;Kaia effectively addresses common blockchain challenges such as network congestion and communication volume by utilizing a fixed-size Committee. This design keeps communication overhead consistent even as the number of Consensus Nodes grows, ensuring efficient and scalable performance. The integration of VRF for Committee selection and multi-channel propagation methods highlights Kaia’s commitment to balancing high throughput with robust security and reliability.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Byzantine Fault: &lt;a href="https://en.wikipedia.org/wiki/Byzantine_fault" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Byzantine_fault&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Kaia Overview: &lt;a href="https://docs.kaia.io/learn/" rel="noopener noreferrer"&gt;https://docs.kaia.io/learn/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Kaia Consensus Mechanism: &lt;a href="https://docs.kaia.io/learn/consensus-mechanism/" rel="noopener noreferrer"&gt;https://docs.kaia.io/learn/consensus-mechanism/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The Istanbul BFT Consensus Algorithm: &lt;a href="https://arxiv.org/pdf/2002.03613" rel="noopener noreferrer"&gt;https://arxiv.org/pdf/2002.03613&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;mawutor (&lt;a href="https://x.com/polymawutor" rel="noopener noreferrer"&gt;@polymawutor&lt;/a&gt;) is a web3 developer with a passion for exploring the latest advancements in blockchain technology. With a focus on providing informative content and building innovative solutions, mawutor aims to demystify complex topics and empower users with actionable insights.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>How To Implement Governance Proposals on Polkadot</title>
      <dc:creator>cyril</dc:creator>
      <pubDate>Mon, 05 Aug 2024 12:59:48 +0000</pubDate>
      <link>https://forem.com/chainparser/how-to-implement-governance-proposals-on-polkadot-10hb</link>
      <guid>https://forem.com/chainparser/how-to-implement-governance-proposals-on-polkadot-10hb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Polkadot, a groundbreaking blockchain platform, empowers its community to shape the network's future through a robust &lt;a href="https://www.investopedia.com/terms/o/onchain-governance.asp" rel="noopener noreferrer"&gt;governance system&lt;/a&gt;. At the heart of this system lies the ability to propose and implement changes to the protocol. Governance proposals leading to &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov#referenda" rel="noopener noreferrer"&gt;referenda&lt;/a&gt; are the vehicles for introducing new features, modifying existing ones, or addressing critical issues within the Polkadot ecosystem. This process is designed to be inclusive, transparent, and community-driven, ensuring that the network evolves in alignment with the collective vision of its stakeholders.&lt;/p&gt;

&lt;p&gt;By participating in &lt;a href="https://polkadot.polkassembly.io/opengov" rel="noopener noreferrer"&gt;OpenGov&lt;/a&gt;, Polkadot's governance process, token holders can actively contribute to the network's development, making informed decisions about its direction. The implementation of governance proposals involves a series of well-defined stages, from the initial proposal submission to the final execution of approved changes. Understanding the mechanics of this process is crucial for anyone seeking to influence the trajectory of the Polkadot ecosystem.&lt;/p&gt;

&lt;p&gt;This post aims to provide a comprehensive overview of OpenGov's Referenda lifecycle on Polkadot, covering key aspects such as creating discussion posts and submitting and implementing proposals. By demystifying the process, this guide empowers community members to effectively engage in governance and contribute to the ongoing success of Polkadot.&lt;/p&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;The term &lt;em&gt;"governance"&lt;/em&gt; originates from the Latin word &lt;em&gt;"gubernare"&lt;/em&gt; meaning &lt;em&gt;"to steer"&lt;/em&gt;. Historically, governance was centralized, akin to steering a ship with a single captain. However, the advent of decentralized systems challenges this traditional top-down approach. &lt;/p&gt;

&lt;p&gt;Decentralization, by distributing control and decision-making across multiple entities, necessitates a reimagining of governance as a collaborative process rather than a hierarchical command structure.&lt;/p&gt;

&lt;p&gt;In Polkadot OpenGov, &lt;a href="https://polkadot.polkassembly.io/referenda" rel="noopener noreferrer"&gt;referenda&lt;/a&gt; are the primary mechanism for steering the network's direction. Similar to voting on a proposal, referenda allow token holders to directly influence the platform's evolution. These referenda are categorized into different tracks based on the nature and impact of the proposed changes, ensuring a tailored approach to decision-making.&lt;/p&gt;

&lt;p&gt;Unlike traditional governance models, Polkadot doesn't have a fixed quorum requirement. Instead, the passage of a referendum depends on achieving specific &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov#approval-and-support" rel="noopener noreferrer"&gt;approval and support&lt;/a&gt; percentages, tailored to the significance of the proposal. This flexible approach ensures that critical decisions require a higher level of consensus while allowing for quicker decisions on less impactful matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  PolkAssembly
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Login
&lt;/h4&gt;

&lt;p&gt;In Polkadot OpenGov, proposals become referenda through the &lt;a href="https://polkadot.polkassembly.io/opengov" rel="noopener noreferrer"&gt;PolkAssembly dApp&lt;/a&gt;, designed to make it easy for the community to get involved in each stage of the process in just a matter of clicks.&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%2Felf3vedwa7a3up5bf9aa.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%2Felf3vedwa7a3up5bf9aa.png" alt="OpenGov dApp Homepage" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before we create a referendum, we'll have to login with our wallet provider. Click the &lt;code&gt;Login&lt;/code&gt; button on the top right corner, and select your preferred wallet provider. &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%2Fho10t7nq4nabihpl19vm.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%2Fho10t7nq4nabihpl19vm.png" alt="Select wallet provider" width="490" height="393"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;After selecting your wallet provider, you'd have to consent to log in again by clicking &lt;code&gt;Got it&lt;/code&gt; and subsequently approving authentication and signature requests&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%2Fc3clluv8nfvnm9xpy8b7.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%2Fc3clluv8nfvnm9xpy8b7.png" alt="Got it" width="490" height="272"&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%2Ffd925mpljj9qxs8px9v5.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%2Ffd925mpljj9qxs8px9v5.png" alt="Approval" width="800" height="475"&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%2Ft5bwiw0yk3zpxa9hghub.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%2Ft5bwiw0yk3zpxa9hghub.png" alt="Approval" width="340" height="545"&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%2Fgtjb2u4z8b677f7eavil.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%2Fgtjb2u4z8b677f7eavil.png" alt="Approval" width="340" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you've signed the signature requests, you'll be presented with a success page and prompted to enter a preferred username.&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%2Fzedx8ok6xr9uwkmv3k6x.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%2Fzedx8ok6xr9uwkmv3k6x.png" alt="Enter username" width="800" height="451"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Provide a username and click &lt;code&gt;Next&lt;/code&gt; which takes you to a modal that prompts for an email address and a password. This stage is optional and you could &lt;code&gt;Skip&lt;/code&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%2Fs4v3ltyna5aiwo74pt7b.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%2Fs4v3ltyna5aiwo74pt7b.png" alt=" " width="492" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The PolkAssembly homepage should be updated, and your username displayed in the top-right corner. &lt;/p&gt;

&lt;h4&gt;
  
  
  Setting Up a Verified On-Chain Identity on PolkAssembly
&lt;/h4&gt;

&lt;p&gt;Polkadot empowers users to create verified digital identities linked to their accounts. This process involves sharing personal information and obtaining confirmation from authorized registrars.&lt;/p&gt;

&lt;p&gt;A verified on-chain identity boosts credibility in Polkadot governance, including referendum proposals. Platforms like PolkAssembly simplify the creation and management of these identities.&lt;/p&gt;

&lt;p&gt;This section walks you through the steps to establish and verify your on-chain identity.&lt;/p&gt;

&lt;h5&gt;
  
  
  Understanding the Process
&lt;/h5&gt;

&lt;p&gt;To establish a verified identity, you'll need to provide personal information such as your name, email, and X.com username. A registrar will review these details to confirm their accuracy.&lt;/p&gt;

&lt;h5&gt;
  
  
  Required Funds and Fees
&lt;/h5&gt;

&lt;p&gt;Some DOT is required for deposit and registrar fees. The exact amount depends on the information you provide, and you'll need sufficient funds to complete this process successfully.&lt;/p&gt;

&lt;h5&gt;
  
  
  Steps to Create Your Identity
&lt;/h5&gt;

&lt;p&gt;Locate your profile name in the top right corner and select &lt;code&gt;Set on-chain identity&lt;/code&gt; from the dropdown menu.&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%2F19l8ohtk5i7zob9vrfg6.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%2F19l8ohtk5i7zob9vrfg6.png" alt="Set on-chain identity" width="800" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose the account you want to use for your on-chain identity and click &lt;code&gt;Confirm&lt;/code&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%2Fh14yx2wygr8pp7xw76qg.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%2Fh14yx2wygr8pp7xw76qg.png" alt="Confirm" width="800" height="643"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following screenshot provides details about setting up an on-chain identity, including fees and required deposits for the People Chain. Click &lt;code&gt;Let's Begin&lt;/code&gt; to start the process.&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%2F4rowuh8g6mo5zoyxjkg8.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%2F4rowuh8g6mo5zoyxjkg8.png" alt="Summarize" width="490" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next screen lets you manage your on-chain identity details. Here, you can enter your display name, legal name, email, and X.com username. &lt;/p&gt;

&lt;p&gt;Conveniently, this window also offers a &lt;code&gt;Teleport Funds&lt;/code&gt; option at the top, allowing you to seamlessly transfer the necessary funds to the People Chain before proceeding. &lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Set Identity&lt;/code&gt; after completing the required details and approve the signature request from the wallet.&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%2Fmazl9qz24dx7b99ke5jc.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%2Fmazl9qz24dx7b99ke5jc.png" alt="Details" width="490" height="584"&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%2Fptv0um52qy16eipe0pg6.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%2Fptv0um52qy16eipe0pg6.png" alt="Teleport" width="486" height="335"&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%2Feso07yzgyoz8q1aohgny.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%2Feso07yzgyoz8q1aohgny.png" alt="Set identity" width="488" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once your transaction is confirmed, you can proceed to the next step: verification.&lt;/p&gt;

&lt;p&gt;Verify your information by clicking the &lt;code&gt;Verify&lt;/code&gt; buttons and following the on-screen instructions. &lt;/p&gt;

&lt;p&gt;Once complete, click &lt;code&gt;Proceed&lt;/code&gt; to submit your identity for review. Please allow some time for PolkAssembly to assess your information.&lt;/p&gt;

&lt;p&gt;Upon approval, your verified identity will be publicly displayed with a green check mark next to your profile. &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%2F7ys0h1vbiflugwvctzjl.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%2F7ys0h1vbiflugwvctzjl.png" alt="Green Check mark" width="63" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations!, now you have a verified on-chain profile! The next section takes a look at creating a discussion post, one of the prerequisites to proposing a referendum.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding A Discussion Post
&lt;/h3&gt;

&lt;p&gt;Before submitting a referendum proposal on OpenGov, &lt;a href="https://polkadot.polkassembly.io/discussions" rel="noopener noreferrer"&gt;a discussion post&lt;/a&gt; is mandatory. This initial step fosters community engagement, allowing for feedback, suggestions, and collaboration. By initiating a discussion, proposers can refine their ideas, gain support, and increase the chances of their proposal gaining traction within the community before formally submitting it as a referendum.&lt;/p&gt;

&lt;p&gt;To add a discussion post, click the &lt;code&gt;Discussions&lt;/code&gt; navigation in the left menu panel and click on &lt;code&gt;Add Post&lt;/code&gt; in the top right corner.&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%2Ff819j6rvqoq2fzu53iz2.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%2Ff819j6rvqoq2fzu53iz2.png" alt="Add Post" width="738" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the new interface, please enter the discussion title in the title box, and in the textarea below, thoroughly describe the proposal, its implications, and benefits to enable community members to make an informed decision.&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%2Fxdssp4n4a6mftgsn0ers.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%2Fxdssp4n4a6mftgsn0ers.png" alt="Discussion Post" width="743" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the subsequent form elements, choose whether you want to add a poll to the discussion, select a topic, or add a tag. You can also open comments on the post to all users, verified users, or even decide to close commenting completely.&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%2Fvplhehnbkmlp56kbthwv.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%2Fvplhehnbkmlp56kbthwv.png" alt="Post settings and metadata" width="727" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you're satisfied with the information provided, click &lt;code&gt;Create Post&lt;/code&gt; which should have your post published as a discussion on the PolkAssembly platform. &lt;/p&gt;

&lt;p&gt;The next section will look at how to propose a referendum on OpenGov. In the meantime, copy the link to the discussion post you just published, it will come in handy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proposing a Referendum
&lt;/h3&gt;

&lt;p&gt;To propose a referendum, navigate back to the &lt;code&gt;Overview&lt;/code&gt; tab, hover over the &lt;em&gt;three-dots&lt;/em&gt; icon at the top-right corner, and click &lt;code&gt;Create Referendum&lt;/code&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%2Fw7v147rrgl6ung2xhk5d.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%2Fw7v147rrgl6ung2xhk5d.png" alt=" " width="306" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will lead to a new modal where you'll be presented with your linked accounts. Make sure you have at least 40 DOT in your linked wallet to be used as a &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov-origins#:~:text=The%20minimum%20amount%20to%20be%20used%20as%20a%20(refundable)%20deposit%20to%20submit%20a%20public%20referendum%20proposal." rel="noopener noreferrer"&gt;submission deposit&lt;/a&gt;. The refundable deposit is required to submit a public referendum proposal.&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Next&lt;/code&gt; to proceed. In the next modal, select &lt;code&gt;Yes&lt;/code&gt; as the answer to the question: &lt;em&gt;Have you initiated a discussion post for your proposal already?&lt;/em&gt;. Paste the link to the discussion post and decide who can comment on the referendum. &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%2Fo5swy6bp4f1h9bas7hz8.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%2Fo5swy6bp4f1h9bas7hz8.png" alt="Proposal first" width="583" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, provide details on the specific outcome desired for the referendum if successful. Then decide on which pallet the referendum falls under and the applicable method. In the example below, we're requesting 200 DOT from the Treasury. For more information on pallets, check out &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov" rel="noopener noreferrer"&gt;this guide&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%2F7idombm2ftoloxvietqj.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%2F7idombm2ftoloxvietqj.png" alt=" " width="583" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, select the applicable type of origin for the chosen &lt;code&gt;Pallet&lt;/code&gt;. In OpenGov, referenda are categorized into &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov-origins" rel="noopener noreferrer"&gt;different Origins and Tracks&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Origins and Tracks
&lt;/h4&gt;

&lt;p&gt;Polkadot's governance system operates on a dual structure of &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov-origins" rel="noopener noreferrer"&gt;Origins and Tracks&lt;/a&gt;. Origins represent different levels of authority within the network, each possessing specific privileges. When submitting a proposal, choosing the correct Origin is crucial as it determines the proposal's execution capabilities. &lt;/p&gt;

&lt;p&gt;Tracks, on the other hand, define the specific rules and parameters for a particular type of proposal. These include factors such as voting duration, required approval thresholds, and the number of concurrent referenda. By combining Origins and Tracks, Polkadot creates a flexible and adaptable governance framework that accommodates various types of proposals and decision-making processes.&lt;/p&gt;

&lt;p&gt;In the next subsections, we'll take a look at the 34 Origins of OpenGov and explain their varying levels of authority. &lt;/p&gt;

&lt;h5&gt;
  
  
  Root
&lt;/h5&gt;

&lt;p&gt;The Root origin holds the highest level of authority within the Polkadot network. It is reserved for the most critical and impactful changes. Referendums under this origin require an exceptionally high level of approval and support from the community to pass. Due to its significance, only one Root referendum can be active at a time.&lt;/p&gt;

&lt;h5&gt;
  
  
  Whitelisted Caller
&lt;/h5&gt;

&lt;p&gt;This origin is used for time-sensitive proposals that require expedited processing. It allows for a shorter voting period compared to other tracks. However, it demands a specific level of support to pass, ensuring a certain level of consensus within the community.&lt;/p&gt;

&lt;h5&gt;
  
  
  Wish For Change
&lt;/h5&gt;

&lt;p&gt;Unlike other origins, Wish For Change is primarily for gathering community sentiment rather than making immediate changes to the network. Proposals under this track serve as a signal for potential future developments and help gauge community interest.&lt;/p&gt;

&lt;h5&gt;
  
  
  Staking Admin
&lt;/h5&gt;

&lt;p&gt;As the name suggests, the Staking Admin origin is responsible for managing staking-related operations. This includes handling slashes, which are penalties imposed on validators for misconduct.&lt;/p&gt;

&lt;h5&gt;
  
  
  Treasurer
&lt;/h5&gt;

&lt;p&gt;The Treasurer origin oversees the management of the Polkadot treasury. It has the authority to approve or reject spending proposals from the treasury.&lt;/p&gt;

&lt;h5&gt;
  
  
  Lease Admin
&lt;/h5&gt;

&lt;p&gt;This origin is responsible for managing slot leases, which are essential for parachains to secure their position on the Polkadot relay chain.&lt;/p&gt;

&lt;h5&gt;
  
  
  Fellowship Admin
&lt;/h5&gt;

&lt;p&gt;The Fellowship Admin origin is dedicated to managing the composition of the Fellowship, a group of elected representatives responsible for various governance tasks.&lt;/p&gt;

&lt;h5&gt;
  
  
  General Admin
&lt;/h5&gt;

&lt;p&gt;The General Admin origin oversees the management of the registrar and permissioned HRMP channels, which are crucial for interoperability between parachains.&lt;/p&gt;

&lt;h5&gt;
  
  
  Auction Admin
&lt;/h5&gt;

&lt;p&gt;The Auction Admin origin is responsible for initiating and managing auctions for parachain slots.&lt;/p&gt;

&lt;h5&gt;
  
  
  Referendum Canceller
&lt;/h5&gt;

&lt;p&gt;This origin has the power to cancel pending referendums under specific conditions.&lt;/p&gt;

&lt;h5&gt;
  
  
  Referendum Killer
&lt;/h5&gt;

&lt;p&gt;This origin can cancel an ongoing referendum and impose penalties on those who initiated it.&lt;/p&gt;

&lt;h5&gt;
  
  
  Small Tipper, Big Tipper, Small Spender, Medium Spender, Big Spender
&lt;/h5&gt;

&lt;p&gt;These origins manage different spending limits from the treasury. They allow for various levels of spending without requiring a full-fledged referendum for smaller amounts.&lt;/p&gt;

&lt;p&gt;Next, choose the applicable Origin for the referendum in the &lt;code&gt;Pallet&lt;/code&gt; and &lt;code&gt;Method&lt;/code&gt; dropdown boxes. &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%2Fr46fut7qrablgqb2w0jw.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%2Fr46fut7qrablgqb2w0jw.png" alt="Create referendum" width="446" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After setting everything up according to your preference, including the right pallet and method, click on &lt;code&gt;Create Referendum&lt;/code&gt; and you should see a successful message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing a Referendum
&lt;/h3&gt;

&lt;p&gt;After a successful proposal, our referendum gets displayed on the overview page on PolkAssembly with a &lt;code&gt;Submitted&lt;/code&gt; tag. This means that the proposal has been published, but we have to satisfy one last requirement before our referendum can be moved to the decision phase.&lt;/p&gt;

&lt;p&gt;For the referendum to move from the preparing phase to the deciding phase, a decision deposit needs to be placed. The decision deposit values for each Treasury Track are listed in &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov-origins#:~:text=Decision%20Deposit%20%2D%20This%20deposit%20is,decision%20period%2C%20it%20gets%20rejected." rel="noopener noreferrer"&gt;this document&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%2F498x5mtmgzgsa3li6iqb.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%2F498x5mtmgzgsa3li6iqb.png" alt="Submitted" width="800" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, to finish off with the implementation, open the proposal page and click on &lt;code&gt;Pay&lt;/code&gt; to make the deposit.&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%2Fscm3qz1fibn7ngavly3l.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%2Fscm3qz1fibn7ngavly3l.png" alt="Pay" width="333" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a successful deposit, you should see the &lt;code&gt;Submitted&lt;/code&gt; tag change to a green &lt;code&gt;Decision&lt;/code&gt; tag. The decision phase allows time for a decision to be approved to move to the confirming period. If the proposal is not approved by the end of the decision period, it gets rejected.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenges and Solutions
&lt;/h2&gt;

&lt;p&gt;Polkadot's OpenGov system faces only a few challenges. The introduction of multiple tracks and origins can increase complexity for users, requiring them to navigate different rules and processes. While the existing 40 DOT submission deposit requirement and proposal curation system help to some extent, the open nature of proposal initiation can still lead to a flood of low-quality or malicious proposals, especially when the price of DOT to levels that make the deposit insignificant. This dilutes the focus on important initiatives and can undermine community trust. &lt;/p&gt;




&lt;h2&gt;
  
  
  Looking Ahead
&lt;/h2&gt;

&lt;p&gt;OpenGov represents a significant evolution in Polkadot's governance model, aiming to create a more inclusive, efficient, and decentralized system for decision-making. As the system matures, it is expected to continue evolving based on community feedback and the changing needs of the network.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Polkadot's OpenGov system offers a robust framework for community-driven decision-making. By understanding the steps involved in proposing and implementing governance proposals, token holders can actively participate in shaping the network's future. &lt;/p&gt;

&lt;p&gt;While challenges exist, such as complexity and the potential for low-quality proposals, ongoing improvements, and community engagement are essential for optimizing the governance process. As Polkadot continues to evolve, OpenGov will play a pivotal role in ensuring the network's long-term success and alignment with the collective vision of its stakeholders.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to Polkadot OpenGov: &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov" rel="noopener noreferrer"&gt;https://wiki.polkadot.network/docs/learn-polkadot-opengov&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Polkadot OpenGov Origins: &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov-origins" rel="noopener noreferrer"&gt;https://wiki.polkadot.network/docs/learn-polkadot-opengov-origins&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Approval and Support: &lt;a href="https://wiki.polkadot.network/docs/learn-polkadot-opengov#approval-and-support" rel="noopener noreferrer"&gt;https://wiki.polkadot.network/docs/learn-polkadot-opengov#approval-and-support&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;mawutor (&lt;a href="https://x.com/polymawutor" rel="noopener noreferrer"&gt;@polymawutor&lt;/a&gt;) is a web3 developer with a passion for exploring the latest advancements in blockchain technology. With a focus on providing informative content and building innovative solutions, mawutor aims to demystify complex topics and empower users with actionable insights.&lt;/p&gt;




</description>
    </item>
    <item>
      <title>How To Perform Cross-Chain Token Transfers with Polkadot XCM</title>
      <dc:creator>cyril</dc:creator>
      <pubDate>Sat, 03 Aug 2024 17:03:44 +0000</pubDate>
      <link>https://forem.com/chainparser/how-to-perform-cross-chain-token-transfers-with-polkadot-xcm-hba</link>
      <guid>https://forem.com/chainparser/how-to-perform-cross-chain-token-transfers-with-polkadot-xcm-hba</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Web3 is expanding into a multi-layered ecosystem of consensus systems spanning diverse blockchains and smart contract applications. This diversity in blockchain architecture and operation highlights the need for interoperability within the ecosystem.&lt;/p&gt;

&lt;p&gt;Consensus systems compete and differentiate themselves based on security, scalability, and decentralization. Some aim for speed with a high-throughput monolith while others focus on scalability and decentralization via layer 2 chains. However, all these diverse consensus systems must be interoperable for the vision of a decentralized web to be achieved.&lt;/p&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Interoperability between chains of different consensus mechanisms is a very arduous endeavor. This is evident in malicious actors exploiting more interoperability solutions over the years. Polkadot, a pioneer in blockchain technology, provides a secure way of cross-chain communication through the Cross-Consensus Message (XCM) format and the Cross-Consensus Messaging Parsing (XCMP).&lt;/p&gt;

&lt;p&gt;XCM is the message format and language used to communicate between consensus systems. Whereas XCMP is the network-layer protocol that facilitates XCM communication. XCM, although commonly used in the Polkadot ecosystem, can be used in any consensus system due to its generic and common format. &lt;/p&gt;

&lt;p&gt;Polkadot XCM is crucial in today's tech landscape as it facilitates seamless interoperability between disparate blockchains. By providing a standardized communication protocol, XCM enables the transfer of assets, data, and messages across different networks, fostering a more interconnected and collaborative ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Structure of XCM
&lt;/h3&gt;

&lt;p&gt;XCM leverages &lt;code&gt;MultiAssets&lt;/code&gt; to represent various assets across blockchains, identified by &lt;code&gt;MultiLocations&lt;/code&gt;. A Holding Register temporarily stores assets during message execution, while Weight signifies the computational resources needed to process the XCM. An XCM message typically follows this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; let message = Xcm(vec![
    WithdrawAsset((Here, amount).into()),
    BuyExecution{ fees: (Here, amount).into(), weight_limit: WeightLimit::Unlimited },
    DepositAsset {
        assets: All.into(),
        beneficiary:  MultiLocation {
            parents: 0,
            interior: Junction::AccountId32 {
                network: None,
                id: BOB.clone().into()
            }.into(),
        }.into()
    }
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;message&lt;/code&gt; consists of three instructions: &lt;code&gt;WithdrawAsset&lt;/code&gt;, &lt;code&gt;BuyExecution&lt;/code&gt;, and &lt;code&gt;DepositAsset&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;WithdrawAsset&lt;/code&gt;: This instruction removes assets from the sender's account and places them in a temporary holding register.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BuyExecution&lt;/code&gt;: This instruction pays for the execution of the XCM message using assets from the holding register.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DepositAsset&lt;/code&gt;: This instruction transfers assets from the holding register to the recipient's account on the target chain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the three instructions are combined, we withdraw the number of native tokens from the account of Alice, pay for the execution of these instructions, and deposit the remaining tokens in the account of Bob in the same consensus system.&lt;/p&gt;

&lt;p&gt;Now let's look at ways to transfer data or assets between accounts on different blockchains utilizing different consensus systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Chain Transfers: Asset Teleportation
&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%2Fac133q6dt7ghs2d8c3ej.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%2Fac133q6dt7ghs2d8c3ej.png" alt=" " width="700" height="311"&gt;&lt;/a&gt;&lt;br&gt;
Asset teleportation is one of the two methods for sending assets from one chain to another. It has only two actors, the source and the destination. &lt;/p&gt;

&lt;p&gt;The source chain removes assets from circulation, creates an XCM instruction specifying the recipient and amount, and sends it to the destination chain. The destination chain then introduces equivalent assets into its circulation and deposits them into the specified account. This process requires high trust between chains as asset preservation relies on both chains accurately managing their respective circulating supplies.&lt;/p&gt;

&lt;p&gt;Let's take a look at an example of an Asset Teleportation XCM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let message = Xcm(vec![
  WithdrawAsset((Here, teleport_amount).into()),
  InitiateTeleport {
    assets: All.into(),
    dest: Parachain(1).into(),
    xcm: Xcm(vec![DepositAsset {
      assets: All.into(),
      beneficiary: Junction::AccountId32 {
        network: None,
        id: ALICE.into(),
      }
    }]),
  },
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's break down the various parts of the message.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;InitiateTeleport&lt;/code&gt; is an XCM instruction executed on the source chain. It removes assets matching the specified filter from the holding register and constructs a new XCM message.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;InitiateTeleport { assets: MultiAssetFilter, dest: MultiLocation, xcm: Xcm&amp;lt;()&amp;gt; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This message includes a &lt;code&gt;ReceiveTeleportedAsset&lt;/code&gt; instruction for the destination chain, followed by the original XCM instructions. The destination chain will automatically process these instructions, effectively teleporting the assets.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ReceiveTeleportedAsset&lt;/code&gt; is a trusted XCM instruction executed on the destination chain. It introduces new assets into circulation, populating the holding register.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReceiveTeleportedAssets(MultiAssets)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This instruction requires strict origin verification to prevent unauthorized asset creation. The destination chain can configure allowed teleporter origins to ensure security. Once assets are in the holding register, subsequent instructions, like &lt;code&gt;DepositAsset&lt;/code&gt;, can be distributed to recipient accounts.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ClearOrigin&lt;/code&gt; resets the message's origin, preventing subsequent instructions from acting on behalf of the previous sender. This is crucial for the security and isolation of XCM message execution contexts. The &lt;code&gt;InitiateTeleport&lt;/code&gt; instruction typically uses &lt;code&gt;ClearOrigin&lt;/code&gt; to ensure the destination chain processes the teleported assets independently.&lt;/p&gt;

&lt;p&gt;Next, we'll look at another way to achieve cross-chain interoperability using reserve-backed transfers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Chain Transfers: Reserve-Backed Transfers
&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%2Feajzkq9ilugl98950mt9.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%2Feajzkq9ilugl98950mt9.png" alt=" " width="800" height="603"&gt;&lt;/a&gt;&lt;br&gt;
Reserve-backed transfers involve a trusted third-party reserve to facilitate cross-chain asset movement. Instead of directly transferring assets, chains mint derivative tokens representing their claims on the reserve. The source chain burns derivative tokens when transferring assets, triggering a withdrawal from its reserve account. &lt;/p&gt;

&lt;p&gt;The reserve then deposits the withdrawn assets into the destination chain's reserve account. Finally, the destination chain mints equivalent derivative tokens for the recipient. This method reduces trust requirements between chains but introduces reliance on the reserve's integrity.&lt;/p&gt;

&lt;p&gt;For instance, transferring tokens from Alice's account on parachain 1 to her account on parachain 2, with the relay chain acting as the reserve, would involve constructing an XCM message to initiate the transfer process. This message would encompass instructions for burning derivative tokens on parachain 1, withdrawing the corresponding amount from the relay chain's reserve, depositing the withdrawn funds into Alice's account on parachain 2, and finally, minting new derivative tokens on parachain 2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let message = Xcm(vec![
  WithdrawAsset((Parent, amount).into()),
  InitiateReserveWithdraw {
    assets: All.into(),
    reserve: Parent.into(),
    xcm: Xcm(vec![DepositReserveAsset {
      assets: All.into(),
      dest: Parachain(2).into(),
      xcm: Xcm(vec![DepositAsset {
        assets: All.into(),
        beneficiary: AccountId32 { id: ALICE.into(), network: None }.into(),
      }]),
    }]),
  },
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The provided XCM message outlines a reserve-backed asset transfer from one parachain to another, utilizing the relay chain as a reserve. Let's break this down:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;InitiateReserveWithdraw&lt;/code&gt; triggers the reserve-backed transfer process. It burns the derivative asset. Sends an XCM message to the relay chain (specified as the reserve).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;InitiateReserveWithdraw { assets: MultiAssetFilter, reserve: MultiLocation, xcm: Xcm&amp;lt;()&amp;gt; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The embedded XCM message contains a &lt;code&gt;WithdrawAsset&lt;/code&gt; instruction to withdraw the underlying asset from the source chain's sovereign account, A &lt;code&gt;ClearOrigin&lt;/code&gt; instruction ensures isolated execution on the relay chain, and a &lt;code&gt;DepositReserveAsset&lt;/code&gt; instruction to transfer the withdrawn asset to the destination chain's sovereign account.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;DepositReserveAsset&lt;/code&gt; instruction serves a dual purpose. It transfers the withdrawn assets to the destination chain's sovereign account, essentially storing them on behalf of the destination.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DepositReserveAsset { assets: MultiAssetFilter, dest: MultiLocation, xcm: Xcm&amp;lt;()&amp;gt; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sends a new XCM message to the destination chain, informing it of the deposited assets and instructing it to mint equivalent derivative tokens. This message includes a &lt;code&gt;ReserveAssetDeposited&lt;/code&gt; instruction for trust verification and a &lt;code&gt;DepositAsset&lt;/code&gt; instruction to credit the recipient's account.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ReserveAssetDeposited&lt;/code&gt; instruction signifies that the reserve chain has successfully transferred assets to the destination chain's sovereign account. Upon receiving this notification, the destination chain mints equivalent derivative assets and credits them to the specified recipient account.&lt;/p&gt;

&lt;p&gt;This instruction requires trust in the reserve chain as it confirms the asset transfer without direct verification. To mitigate risks, the destination chain can configure which chains are trusted as reserves for specific assets.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenges and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fee Handling In XCM
&lt;/h3&gt;

&lt;p&gt;XCM messages require fee payments to execute. The &lt;code&gt;BuyExecution&lt;/code&gt; instruction is used to purchase the necessary weight for message execution. Accurate fee estimation is crucial to prevent message failures.&lt;/p&gt;

&lt;p&gt;Here are some fee payment mechanisms you can utilize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prepaid Fees: The standard approach involves including a &lt;code&gt;BuyExecution&lt;/code&gt; instruction with sufficient funds to cover estimated execution costs.&lt;/li&gt;
&lt;li&gt;Direct Withdrawal: The &lt;code&gt;SetFeesMode&lt;/code&gt; instruction allows fees to be directly withdrawn from the sender's account, useful for unpredictable fee scenarios.&lt;/li&gt;
&lt;li&gt;Unpaid Execution: The &lt;code&gt;UnpaidExecution&lt;/code&gt; instruction can be used for privileged messages that don't require fee payments, but require careful configuration and trust in the message origin.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fee Management and Error Handling
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;RefundSurplus&lt;/code&gt; instruction can be used within error handlers to reclaim unused weight if a message fails to execute completely. Accurate weight estimation is essential to avoid overpaying fees. By effectively managing fees and handling potential errors, XCM messages can be executed reliably and efficiently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let message = Xcm(vec![
  WithdrawAsset((Parent, message_fee).into()),
  BuyExecution {
    fees: (Parent, message_fee).into(),
    weight_limit: WeightLimit::Unlimited,
  },
  SetErrorHandler(Xcm(vec![
    RefundSurplus,
    DepositAsset {
      assets: All.into(),
      beneficiary: AccountId32 {
        network: Some(ByGenesis([0; 32])),
        id: relay_sovereign_account_id().into(),
      }
      .into(),
    },
  ])),
  Trap(1),
  ClearOrigin,
  ClearOrigin,
  ClearOrigin,
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, we pay upfront for all the instructions in the XCM. When the &lt;code&gt;Trap&lt;/code&gt; instruction throws an error, the error handler will be called and the weight for all the instructions that weren't executed is refunded.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article explored the core structure of XCM messages, the concept of MultiAssets and MultiLocations, and the Holding Register. We delved into the mechanics of asset teleportation and reserve-backed transfers, highlighting the trust assumptions involved in each method. Finally, we discussed the importance of fee handling in XCM messages and explored different fee payment mechanisms.&lt;/p&gt;

&lt;p&gt;By understanding these core concepts, developers can construct secure and interoperable cross-chain applications using XCM. Want to delve deeper? The XCM documentation provides comprehensive examples to illustrate various XCM use cases in detail: &lt;a href="https://github.com/polkadot-fellows/xcm-format" rel="noopener noreferrer"&gt;https://github.com/polkadot-fellows/xcm-format&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This concludes our exploration of Polkadot's XCM, the powerful language facilitating seamless communication between blockchains.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to Cross-Consensus Message Format (XCM): &lt;a href="https://wiki.polkadot.network/docs/learn-xcm" rel="noopener noreferrer"&gt;https://wiki.polkadot.network/docs/learn-xcm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;XCM: Cross-Consensus Messaging: &lt;a href="https://wiki.polkadot.network/docs/learn/xcm/introduction" rel="noopener noreferrer"&gt;https://wiki.polkadot.network/docs/learn/xcm/introduction&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The XCVM: &lt;a href="https://wiki.polkadot.network/docs/learn/xcm/overview-xcvm" rel="noopener noreferrer"&gt;https://wiki.polkadot.network/docs/learn/xcm/overview-xcvm&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;mawutor (&lt;a href="https://x.com/polymawutor" rel="noopener noreferrer"&gt;@polymawutor&lt;/a&gt;) is a web3 developer with a passion for exploring the latest advancements in blockchain technology. With a focus on providing informative content and building innovative solutions, mawutor aims to demystify complex topics and empower users with actionable insights.&lt;/p&gt;




</description>
    </item>
  </channel>
</rss>
