<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>otor</title>
        <link>https://paragraph.com/@otor</link>
        <description>undefined</description>
        <lastBuildDate>Wed, 15 Apr 2026 14:41:37 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>otor</title>
            <url>https://storage.googleapis.com/papyrus_images/91812b54f7c50ac77d0def07dd4f2aff769483b03978bf71361e6a53c870aaff.png</url>
            <link>https://paragraph.com/@otor</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Data-Structures in Modern DeFi (For Developers, Auditors, and Researchers)]]></title>
            <link>https://paragraph.com/@otor/data-structures-in-modern-defi-for-developers-auditors-and-researchers</link>
            <guid>dacrEhIo90YW8WxYTKax</guid>
            <pubDate>Sat, 27 Sep 2025 21:02:02 GMT</pubDate>
            <description><![CDATA[IntroductionMost DeFi protocols are reinventing the wheel with basic data structures. Your AMM is doing O(n) liquidity queries when it could be O(log n), and your lending protocol is iterating through arrays when bitmaps exist. Your DEX is wasting 50k+ gas on operations that could cost 3k. If your background isn&apos;t in computer science, and you are in the blockchain space, you might find it difficult to maintain your position in the industry, either as a Builder, Auditor, or Researcher, as...]]></description>
            <content:encoded><![CDATA[<h2 id="h-introduction" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Introduction</h2><p><strong>Most DeFi protocols are reinventing the wheel with basic data structures.</strong></p><p>Your AMM is doing O(n) liquidity queries when it could be O(log n), and your lending protocol is iterating through arrays when bitmaps exist. Your DEX is wasting 50k+ gas on operations that could cost 3k.</p><p>If your background isn&apos;t in computer science, and you are in the blockchain space, you might find it difficult to maintain your position in the industry, either as a Builder, Auditor, or Researcher, as more and more projects are adopting complex data structures to improve performance.</p><p>🔥 <strong>The gap is widening:</strong></p><ul><li><p><strong>Junior devs write loops, senior devs write trees</strong></p></li><li><p><strong>Basic auditors check logic, elite auditors spot vulnerabilities</strong></p></li><li><p><strong>Researchers who understand data structures predict the next breakthrough</strong></p></li></ul><p>As a Builder, Auditor, or Researcher post-2024, you can&apos;t afford to ignore data structures anymore.</p><p>I&apos;ve compiled production-ready implementations of the data structures and a simple, understandable codebase that simplifies each of these protocols&apos; data structures. This document explores the shift from traditional DeFi implementations to Tree and Graph-based architectures, highlighting their advantages, design patterns, and real-world applications through detailed case studies of live production protocols.</p><h2 id="h-understanding-trees-and-graphs-the-foundation" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Understanding Trees and Graphs: The Foundation</h2><p>Before diving into DeFi applications, let&apos;s establish a solid understanding of these fundamental data structures. Whether you&apos;re a seasoned developer or new to computer science, this section will provide the conceptual foundation needed to understand their revolutionary application in DeFi protocols.</p><h3 id="h-what-are-trees" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">What Are Trees?</h3><p>A <strong>tree</strong> is a hierarchical data structure that organizes data in a parent-child relationship. Think of it like a family tree or an organizational chart - there&apos;s a clear hierarchy with one root at the top, and each element (called a &quot;node&quot;) can have children below it.</p><h4 id="h-key-tree-characteristics" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Key Tree Characteristics</h4><ul><li><p><strong>Root</strong>: The topmost node (like a CEO in a company)</p></li><li><p><strong>Parent/Child</strong>: Each node can have children, and each child has exactly one parent</p></li><li><p><strong>Leaf</strong>: Nodes with no children (like employees with no direct reports)</p></li><li><p><strong>Depth</strong>: How many levels deep does the tree go</p></li><li><p><strong>Path</strong>: The route from one node to another</p></li></ul><h4 id="h-visual-example" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Visual Example:</h4><pre data-type="codeBlock" text="        Root (CEO)
       /          \
   Manager A    Manager B
   /      \         |
John    Sarah    Alice
"><code>        Root (CEO)
       <span class="hljs-operator">/</span>          \
   Manager A    Manager B
   <span class="hljs-operator">/</span>      \         <span class="hljs-operator">|</span>
John    Sarah    Alice
</code></pre><h4 id="h-types-of-trees-in-defi" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Types of Trees in DeFi</h4><ol><li><p><strong>Binary Trees</strong>: Each node has at most 2 children (Manager A has John and Sarah)</p></li><li><p><strong>Segment Trees</strong>: Specialized for range queries and updates</p></li><li><p><strong>Merkle Trees</strong>: Used for cryptographic proofs (not covered in this doc)</p></li></ol><h3 id="h-what-are-graphs" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">What Are Graphs?</h3><p>A <strong>graph</strong> is a more flexible structure consisting of <strong>vertices</strong> (nodes) connected by <strong>edges</strong> (connections). Unlike trees, graphs can have cycles and multiple paths between nodes. Think of it like a city road network - intersections (vertices) are connected by roads (edges), and you might reach the same destination through different route combinations.</p><h4 id="h-key-graph-characteristics" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Key Graph Characteristics</h4><ul><li><p><strong>Vertices (Nodes)</strong>: The entities in the graph (intersections, tokens, pools)</p></li><li><p><strong>Edges</strong>: The connections between vertices (roads, swap pairs)</p></li><li><p><strong>Directed vs Undirected</strong>: Whether connections have direction (one-way vs two-way)</p></li><li><p><strong>Cycles</strong>: Circular paths (A connects to B, B to C, C back to A)</p></li><li><p><strong>Connected Components</strong>: Groups of vertices that can reach each other</p></li></ul><h4 id="h-visual-example" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Visual Example:</h4><pre data-type="codeBlock" text="    Paris ---- Amsterdam ---- Madrid
    |             |             |
    |             |             |
    London ---- Berlin --------/
"><code>    Paris <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> Amsterdam <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> Madrid
    <span class="hljs-operator">|</span>             <span class="hljs-operator">|</span>             <span class="hljs-operator">|</span>
    <span class="hljs-operator">|</span>             <span class="hljs-operator">|</span>             <span class="hljs-operator">|</span>
    London <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span> Berlin <span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">-</span><span class="hljs-operator">/</span>
</code></pre><p>In this graph, you can travel from Paris to Madrid via multiple paths: Paris→Amsterdam→Madrid (direct, 2 hops), Paris→London→Berlin→Madrid (longer, 3 hops), or Paris→Amsterdam→Berlin→Madrid (alternative, 3 hops).</p><h3 id="h-trees-vs-graphs-when-to-use-which" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Trees vs Graphs: When to Use Which?</h3><ul><li><p><strong>Structure Differences:</strong> <strong>Trees</strong> maintain hierarchical organization without cycles, while <strong>graphs</strong> allow flexible connectivity with potential cycles and complex network relationships.</p></li><li><p><strong>Primary Use Cases:</strong> <strong>Trees</strong> are optimized for range queries and hierarchical data management, whereas <strong>graphs</strong> excel in network relationships and pathfinding scenarios.</p></li><li><p><strong>DeFi Applications:</strong> <strong>Trees</strong> handle price ranges and liquidity tiers effectively, while <strong>graphs</strong> manage token swap routing and pool connections across multiple assets.</p></li><li><p><strong>Implementation Complexity:</strong> <strong>Trees</strong> offer simpler traversal and implementation patterns, while <strong>graphs</strong> require more sophisticated algorithms but enable richer relationship modeling.</p></li></ul><h3 id="h-why-traditional-arraysmappings-arent-enough" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Why Traditional Arrays/Mappings Aren&apos;t Enough</h3><p>In early DeFi (2020-2022), most protocols used simple data structures:</p><pre data-type="codeBlock" text="// Traditional approach - simple but inefficient
mapping(address =&gt; uint256) balances;  // O(1) lookup, but no relationships
uint256[] prices;                      // O(n) for range operations
mapping(uint256 =&gt; uint256) liquidityByTick; // O(n) for multi-tick updates
"><code><span class="hljs-comment">// Traditional approach - simple but inefficient</span>
<span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">address</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">uint256</span>) balances;  <span class="hljs-comment">// O(1) lookup, but no relationships</span>
<span class="hljs-keyword">uint256</span>[] prices;                      <span class="hljs-comment">// O(n) for range operations</span>
<span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">uint256</span>) liquidityByTick; <span class="hljs-comment">// O(n) for multi-tick updates</span>
</code></pre><p><strong>Problems with traditional approaches:</strong></p><ul><li><p><strong>Linear complexity</strong>: Updating multiple related items requires individual operations</p></li><li><p><strong>No relationships</strong>: Can&apos;t efficiently model connections between tokens/pools</p></li><li><p><strong>Gas inefficiency</strong>: Each operation costs gas; multiple operations cost multiple gas</p></li><li><p><strong>Limited queries</strong>: Hard to ask &quot;what&apos;s the total liquidity in this price range?&quot;</p></li></ul><h3 id="h-how-trees-and-graphs-solve-these-problems-you-will-write-more-code" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">How Trees and Graphs Solve These Problems (you will write more code)</h3><h4 id="h-trees-solve-range-operations" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Trees Solve Range Operations:</h4><pre data-type="codeBlock" text="// Tree approach - efficient range updates
function updateLiquidityRange(uint256 start, uint256 end, uint256 amount) {
    // O(log n) instead of O(n) - exponentially better!
    tree.updateRange(start, end, amount);
}
"><code><span class="hljs-comment">// Tree approach - efficient range updates</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateLiquidityRange</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> start, <span class="hljs-keyword">uint256</span> end, <span class="hljs-keyword">uint256</span> amount</span>) </span>{
    <span class="hljs-comment">// O(log n) instead of O(n) - exponentially better!</span>
    tree.updateRange(start, end, amount);
}
</code></pre><h4 id="h-graphs-solve-routing-and-relationships" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Graphs Solve Routing and Relationships:</h4><pre data-type="codeBlock" text="// Graph approach - model complex token relationships
function findBestSwapPath(address tokenA, address tokenB) returns (address[] path) {
    // Can find optimal multi-hop routes through connected pools
    return graph.shortestPath(tokenA, tokenB);
}
"><code><span class="hljs-comment">// Graph approach - model complex token relationships</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">findBestSwapPath</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> tokenA, <span class="hljs-keyword">address</span> tokenB</span>) <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">address</span>[] path</span>) </span>{
    <span class="hljs-comment">// Can find optimal multi-hop routes through connected pools</span>
    <span class="hljs-keyword">return</span> graph.shortestPath(tokenA, tokenB);
}
</code></pre><h2 id="h-the-evolution-from-traditional-to-tree-based-defi" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Evolution from Traditional to Tree-Based DeFi</h2><h3 id="h-traditional-defi-patterns-pre-2023" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Traditional DeFi Patterns (Pre-2023)</h3><ul><li><p><strong>Linear Array Storage</strong>: Most early AMMs used simple array-based liquidity tracking</p></li><li><p><strong>Hash Map Lookups</strong>: Price discovery through basic mapping structures</p></li><li><p><strong>Sequential Processing</strong>: Order matching and liquidity provision in linear time</p></li><li><p><strong>Gas Inefficiency</strong>: O(n) operations for price updates and range queries</p></li></ul><h3 id="h-modern-patterns-2023-present" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Modern Patterns (2023-Present)</h3><ul><li><p><strong>Hierarchical Data Organization</strong>: Multi-level tree structures for efficient range queries</p></li><li><p><strong>Logarithmic Complexity</strong>: O(log n) operations for most critical functions</p></li><li><p><strong>Spatial Indexing</strong>: Tree-based tick and price range management</p></li><li><p><strong>Optimized Gas Usage</strong>: Batch operations and efficient traversal algorithms</p></li></ul><h2 id="h-why-trees-matter-in-defi" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why Trees Matter in DeFi</h2><h3 id="h-1-liquidity-range-management" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">1. <strong>Liquidity Range Management</strong></h3><p>Modern concentrated liquidity protocols need to:</p><ul><li><p>Efficiently find active liquidity at specific price points</p></li><li><p>Update multiple price ranges simultaneously</p></li><li><p>Handle range overlaps and merging</p></li></ul><p><strong>Traditional Approach:</strong></p><pre data-type="codeBlock" text="// O(n) complexity for range updates
mapping(uint256 =&gt; uint256) liquidityByTick;
function updateLiquidity(uint256[] memory ticks, uint256[] memory amounts) {
    for (uint i = 0; i &lt; ticks.length; i++) {
        liquidityByTick[ticks[i]] += amounts[i];
    }
}
"><code><span class="hljs-comment">// O(n) complexity for range updates</span>
<span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">uint256</span>) liquidityByTick;
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateLiquidity</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span>[] <span class="hljs-keyword">memory</span> ticks, <span class="hljs-keyword">uint256</span>[] <span class="hljs-keyword">memory</span> amounts</span>) </span>{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint</span> i <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i <span class="hljs-operator">&#x3C;</span> ticks.<span class="hljs-built_in">length</span>; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
        liquidityByTick[ticks[i]] <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amounts[i];
    }
}
</code></pre><p><strong>Tree-Based Approach:</strong></p><pre data-type="codeBlock" text="// O(log n) complexity using tree structure
function updateLiquidityRange(uint256 lowerTick, uint256 upperTick, uint256 amount) {
    tree.updateRange(lowerTick, upperTick, amount);
}
"><code><span class="hljs-comment">// O(log n) complexity using tree structure</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateLiquidityRange</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> lowerTick, <span class="hljs-keyword">uint256</span> upperTick, <span class="hljs-keyword">uint256</span> amount</span>) </span>{
    tree.updateRange(lowerTick, upperTick, amount);
}
</code></pre><h2 id="h-tree-design-patterns-in-production-defi" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Tree Design Patterns in Production DeFi</h2><p>As I journeyed through various DeFi protocols during development, audits, and research, I discovered several innovative tree and graph-based design patterns that have been successfully implemented in production environments. Here are some notable examples:</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/71f325b5939a9b36cc0312b95f961d1a5e8eace609dcfd5d75552e78820fc4d1.png" alt="Data-structure/traditional arrays and mapping" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Data-structure/traditional arrays and mapping</figcaption></figure><h3 id="h-burve-protocol-graph-based-system" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Burve Protocol Graph-Based System</h3><h2 id="h-system-overview" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">System Overview</h2><p>The Burve protocol, written as a Diamond pattern, implements a graph-based liquidity pool system. When you think of Graph, you think of nodes (Vertices) connected (Edges) and finding the shortest path between them, which is a key aspect in terms of developing Graph Algorithms in solidity, especially when it comes to optimizing gas costs and ensuring efficient data retrieval. Unlike trees, a graph is not hierarchical but a collection of nodes and edges, so a vertice can connect to multiple edges and form complex relationships.</p><ul><li><p><strong>Vertices</strong> represent tokens/assets (You can call it nodes- (tokens, vaults, reserves))</p></li><li><p><strong>Closures</strong> represent groups of tokens (vertices) that can be swapped with each other (subgraphs). Think of it like a subgraph within the larger graph structure, where all tokens (Vertices) in the closure are interconnected and can be swapped directly with one another.</p></li><li><p><strong>Value Tokens</strong> represent shares in the overall liquidity system (you can think of it as a representation of the value of the assets in the system)</p></li><li><p><strong>Edges</strong> are implicitly defined by closures (tokens in the same closure can be swapped). You can think of it as the connections between nodes in a graph.</p></li></ul><h2 id="h-basic-burve-graph-structure" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Basic Burve Graph Structure</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/6d308089e8fcfb95f469a5e1cac0af83cb5343d1f4e4b1036c71cde48945a1a5.png" alt="burve-protocol Graph Structure" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">burve-protocol Graph Structure</figcaption></figure><h2 id="h-how-swapping-works" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How Swapping Works</h2><h3 id="h-simple-example-eth-dai-swap" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Simple Example: ETH → DAI Swap</h3><p>While this is similar to how you set path in Uniswap, the key difference is that in Burve, you don&apos;t have to deploy multiple pools of contracts; tokens are grouped into closures (Nodes), and swaps can only occur directly between tokens within the same closure(Node). If two tokens are not in the same closure (Node), a multi-hop swap through bridge tokens (tokens that exist in multiple closures (Nodes) is required. Unlike when a pool can only have 1 pair of tokens, in Burve, each closure (Node) can contain multiple tokens, allowing for more complex swap paths and better liquidity distribution, and you only have to pay fees for the closures you use.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8c248be52a94da7a7081489b4028bba2cca9bf5694fc2d6df81150e5f60afa46.png" alt="trx journey burve-protocol" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">trx journey burve-protocol</figcaption></figure><h3 id="h-simple-implementation-optimal-design" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Simple implementation: Optimal Design</h3><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract BurveGraphSimplified {
    // Core graph structures
    struct Vertex {
        uint256 id;
        address tokenAddress;
        string tokenType; // &quot;token&quot;, &quot;vault&quot;, &quot;reserve&quot;
        uint256 balance;
    }
    
    struct Closure {
        uint256 id;
        string name;
        uint256[] vertexIds; // Vertices in this closure
        bool active;
    }
    
    // Global mappings (like actual Burve)
    mapping(uint256 =&gt; Vertex) public vertices;
    mapping(uint256 =&gt; Closure) public closures;
    mapping(uint256 =&gt; mapping(uint256 =&gt; bool)) public vertexInClosure;
    
    uint256 public nextVertexId = 1;
    uint256 public nextClosureId = 1;
    
    // Create a new closure (protocol function, not user)
    function createClosure(string memory _name) external returns (uint256) {
        uint256 closureId = nextClosureId++;
        closures[closureId] = Closure(closureId, _name, new uint256Unsupported embed, true);
        return closureId;
    }
    
    // Add vertex to system
    function addVertex(address _tokenAddress, string memory _tokenType) external returns (uint256) {
        uint256 vertexId = nextVertexId++;
        vertices[vertexId] = Vertex(vertexId, _tokenAddress, _tokenType, 0);
        return vertexId;
    }
    
    // Add vertex to closure (creates implicit edges)
    function addVertexToClosure(uint256 _vertexId, uint256 _closureId) external {
        require(vertices[_vertexId].id != 0, &quot;Vertex doesn&apos;t exist&quot;);
        require(closures[_closureId].id != 0, &quot;Closure doesn&apos;t exist&quot;);
        
        closures[_closureId].vertexIds.push(_vertexId);
        vertexInClosure[_vertexId][_closureId] = true;
    }
    
    // Check if two vertices can swap directly (same closure)
    function canSwapDirect(uint256 _fromVertex, uint256 _toVertex) external view returns (bool) {
        // Check if both vertices exist in the same closure
        for (uint256 i = 1; i &lt; nextClosureId; i++) {
            if (vertexInClosure[_fromVertex][i] &amp;&amp; vertexInClosure[_toVertex][i]) {
                return true;
            }
        }
        return false;
    }
    
    // Find swap path (simplified)
    function findSwapPath(uint256 _fromVertex, uint256 _toVertex) 
        external view returns (uint256[] memory path) {
        // Simplified: find common closure or bridge vertex
        // In real implementation, this would use graph algorithms
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">BurveGraphSimplified</span> </span>{
    <span class="hljs-comment">// Core graph structures</span>
    <span class="hljs-keyword">struct</span> <span class="hljs-title">Vertex</span> {
        <span class="hljs-keyword">uint256</span> id;
        <span class="hljs-keyword">address</span> tokenAddress;
        <span class="hljs-keyword">string</span> tokenType; <span class="hljs-comment">// "token", "vault", "reserve"</span>
        <span class="hljs-keyword">uint256</span> balance;
    }
    
    <span class="hljs-keyword">struct</span> <span class="hljs-title">Closure</span> {
        <span class="hljs-keyword">uint256</span> id;
        <span class="hljs-keyword">string</span> name;
        <span class="hljs-keyword">uint256</span>[] vertexIds; <span class="hljs-comment">// Vertices in this closure</span>
        <span class="hljs-keyword">bool</span> active;
    }
    
    <span class="hljs-comment">// Global mappings (like actual Burve)</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> Vertex) <span class="hljs-keyword">public</span> vertices;
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> Closure) <span class="hljs-keyword">public</span> closures;
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">bool</span>)) <span class="hljs-keyword">public</span> vertexInClosure;
    
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> nextVertexId <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">public</span> nextClosureId <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
    
    <span class="hljs-comment">// Create a new closure (protocol function, not user)</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createClosure</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _name</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">uint256</span> closureId <span class="hljs-operator">=</span> nextClosureId<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
        closures[closureId] <span class="hljs-operator">=</span> Closure(closureId, _name, <span class="hljs-keyword">new</span> uint256Unsupported embed, <span class="hljs-literal">true</span>);
        <span class="hljs-keyword">return</span> closureId;
    }
    
    <span class="hljs-comment">// Add vertex to system</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addVertex</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> _tokenAddress, <span class="hljs-keyword">string</span> <span class="hljs-keyword">memory</span> _tokenType</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-keyword">uint256</span> vertexId <span class="hljs-operator">=</span> nextVertexId<span class="hljs-operator">+</span><span class="hljs-operator">+</span>;
        vertices[vertexId] <span class="hljs-operator">=</span> Vertex(vertexId, _tokenAddress, _tokenType, <span class="hljs-number">0</span>);
        <span class="hljs-keyword">return</span> vertexId;
    }
    
    <span class="hljs-comment">// Add vertex to closure (creates implicit edges)</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addVertexToClosure</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _vertexId, <span class="hljs-keyword">uint256</span> _closureId</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        <span class="hljs-built_in">require</span>(vertices[_vertexId].id <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Vertex doesn't exist"</span>);
        <span class="hljs-built_in">require</span>(closures[_closureId].id <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Closure doesn't exist"</span>);
        
        closures[_closureId].vertexIds.<span class="hljs-built_in">push</span>(_vertexId);
        vertexInClosure[_vertexId][_closureId] <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    }
    
    <span class="hljs-comment">// Check if two vertices can swap directly (same closure)</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">canSwapDirect</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _fromVertex, <span class="hljs-keyword">uint256</span> _toVertex</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-comment">// Check if both vertices exist in the same closure</span>
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">uint256</span> i <span class="hljs-operator">=</span> <span class="hljs-number">1</span>; i <span class="hljs-operator">&#x3C;</span> nextClosureId; i<span class="hljs-operator">+</span><span class="hljs-operator">+</span>) {
            <span class="hljs-keyword">if</span> (vertexInClosure[_fromVertex][i] <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> vertexInClosure[_toVertex][i]) {
                <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
            }
        }
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
    }
    
    <span class="hljs-comment">// Find swap path (simplified)</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">findSwapPath</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> _fromVertex, <span class="hljs-keyword">uint256</span> _toVertex</span>) 
        <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span>[] <span class="hljs-keyword">memory</span> path</span>) </span>{
        <span class="hljs-comment">// Simplified: find common closure or bridge vertex</span>
        <span class="hljs-comment">// In real implementation, this would use graph algorithms</span>
    }
}
</code></pre><p>This is the basic structure of how the graph is represented in Burve and how swaps are facilitated through closures. The actual implementation would be more complex, especially in terms of pathfinding and optimizing for gas costs, but this gives a foundational understanding of the graph-based approach in the Burve protocol.</p><h3 id="h-ammplify-protocol-binary-tree-system" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Ammplify Protocol Binary Tree System</h3><h2 id="h-system-overview" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">System Overview</h2><p>The Ammplify protocol implements a <strong>binary tree-based liquidity management system</strong> built as a Diamond proxy pattern. Unlike traditional AMMs that process liquidity linearly tick-by-tick, Ammplify organizes price ranges into a hierarchical binary tree structure that enables efficient range operations and dramatic gas optimizations.</p><p>To give a short illustration of what Binary Tree is: When you think of Binary Tree, you think of a hierarchical structure where each node has at most two children (left and right), unlike graphs where nodes can connect to multiple other nodes. In trees, there&apos;s exactly one path between any two nodes, and there&apos;s a clear parent-child relationship with a single root at the top. Let me not bore you with Tree explanation. In Ammplify, the binary tree consists of:</p><ul><li><p><strong>Nodes</strong> represent price ranges (ticks) with different granularities - each covering a specific width of price space</p></li><li><p><strong>Keys</strong> uniquely identify each node using base + width encoding packed into 48-bit values</p></li><li><p><strong>Routes</strong> define optimal paths through the tree for range operations (like updating liquidity from tick 100 to 200)</p></li><li><p><strong>Walkers</strong> traverse the tree to update liquidity and balances using the calculated routes</p></li><li><p><strong>LCA (Lowest Common Ancestor)</strong> optimizes tree traversal by finding the smallest subtree containing the target range</p></li></ul><h2 id="h-basic-binary-tree-structure" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Basic Binary Tree Structure</h2><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/96b2f717b324f1c0b31fae9d7355473e6c43a60a68d5ec48b7d8b4e82b782e24.png" alt="Ammplify-xyz tree structure" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Ammplify-xyz tree structure</figcaption></figure><h2 id="h-how-range-updates-work" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How Range Updates Work</h2><h3 id="h-simple-example-add-liquidity-to-range-4-7" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Simple Example: Add Liquidity to Range [4, 7]</h3><p>While this is similar to how you might update multiple ticks in Uniswap, the key difference is that in Ammplify, liquidity operations are organized into a tree structure where range updates follow optimal paths through the tree hierarchy. Unlike when you have to update each tick individually, in Ammplify, the tree walker finds the Lowest Common Ancestor (LCA) that covers your range and efficiently updates only the necessary nodes, allowing for logarithmic complexity instead of linear operations, and you only pay gas for the nodes you actually modify.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/8c248be52a94da7a7081489b4028bba2cca9bf5694fc2d6df81150e5f60afa46.png" alt="Ammplify-xyz trx flow" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Ammplify-xyz trx flow</figcaption></figure><h3 id="h-simple-implementation-optimal-design" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Simple implementation: Optimal Design</h3><pre data-type="codeBlock" text="// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract AmmplifyTreeSimplified {
    struct TreeNode {
        uint24 base;        // Starting tick
        uint24 width;       // Range width (power of 2)
        uint128 liquidity;  // Liquidity at this node
        uint128 subtreeLiq; // Total liquidity in subtree
    }
    
    // Tree storage: Key (base, width) -&gt; Node data
    mapping(uint48 =&gt; TreeNode) public nodes;
    uint24 public rootWidth;
    
    // Initialize the tree with a root width (must be power of 2)
    constructor(uint24 _rootWidth) {
        require(_rootWidth &gt; 0 &amp;&amp; (_rootWidth &amp; (_rootWidth - 1)) == 0, &quot;Root width must be power of 2&quot;);
        rootWidth = _rootWidth;
    }
    
    // Create tree key from base and width
    function makeKey(uint24 base, uint24 width) public pure returns (uint48) {
        return (uint48(width) &lt;&lt; 24) | base;
    }
    
    // Add liquidity to a range [left, right]
    function addLiquidity(uint24 left, uint24 right, uint128 amount) external {
        require(left &lt;= right, &quot;Invalid range&quot;);
        require(right &lt; rootWidth, &quot;Range exceeds tree bounds&quot;);
        
        // Use simplified iterative approach
        _updateRange(left, right, amount);
    }
    
    // ITERATIVE tree walking (simplified Ammplify LCA approach)
    function _updateRange(uint24 left, uint24 right, uint128 amount) internal {
        // 1. Find LCA that contains the range (like real Ammplify)
        uint24 lcaWidth = findLCAWidth(left, right);
        uint24 lcaBase = left &amp; ~(lcaWidth - 1);
        
        // 2. Walk down from root to LCA, updating subtree totals
        uint24 currentBase = 0;
        uint24 currentWidth = rootWidth;
        
        while (currentWidth &gt; lcaWidth) {
            uint48 key = makeKey(currentBase, currentWidth);
            nodes[key].subtreeLiq += amount * lcaWidth;  // Width-weighted like Ammplify
            
            // Navigate toward LCA
            uint24 midPoint = currentBase + currentWidth / 2;
            if (lcaBase &lt; midPoint) {
                currentWidth /= 2;  // Go left
            } else {
                currentBase = midPoint;  // Go right
                currentWidth /= 2;
            }
        }
        
        // 3. Update the LCA node itself
        uint48 lcaKey = makeKey(lcaBase, lcaWidth);
        nodes[lcaKey].subtreeLiq += amount * lcaWidth;
        
        // 4. If LCA exactly matches our range, add direct liquidity
        if (lcaBase == left &amp;&amp; (lcaBase + lcaWidth - 1) == right) {
            nodes[lcaKey].liquidity += amount;
        } else {
            // 5. Otherwise, recursively update children (simplified)
            _updateLCAChildren(lcaBase, lcaWidth, left, right, amount);
        }
    }
    
    // Handle range updates within the LCA subtree
    function _updateLCAChildren(uint24 base, uint24 width, uint24 left, uint24 right, uint128 amount) internal {
        if (width == 1) {
            // Leaf node - add direct liquidity
            uint48 key = makeKey(base, width);
            nodes[key].liquidity += amount;
            return;
        }
        
        uint24 midPoint = base + width / 2;
        uint24 leftWidth = width / 2;
        uint24 rightWidth = width / 2;
        
        // Update left child if range overlaps
        if (left &lt; midPoint) {
            uint48 leftKey = makeKey(base, leftWidth);
            uint24 leftEnd = min(right, midPoint - 1);
            uint24 childAmount = (leftEnd - left + 1);
            nodes[leftKey].subtreeLiq += childAmount * amount;
            
            if (base == left &amp;&amp; (base + leftWidth - 1) == leftEnd) {
                nodes[leftKey].liquidity += amount;
            } else if (leftWidth &gt; 1) {
                _updateLCAChildren(base, leftWidth, left, leftEnd, amount);
            }
        }
        
        // Update right child if range overlaps  
        if (right &gt;= midPoint) {
            uint48 rightKey = makeKey(midPoint, rightWidth);
            uint24 rightStart = max(left, midPoint);
            uint24 childAmount = (right - rightStart + 1);
            nodes[rightKey].subtreeLiq += childAmount * amount;
            
            if (midPoint == rightStart &amp;&amp; (midPoint + rightWidth - 1) == right) {
                nodes[rightKey].liquidity += amount;
            } else if (rightWidth &gt; 1) {
                _updateLCAChildren(midPoint, rightWidth, rightStart, right, amount);
            }
        }
    }
    
    // Query liquidity at a specific tick
    function getLiquidityAt(uint24 tick) external view returns (uint128 totalLiq) {
        require(tick &lt; rootWidth, &quot;Tick out of bounds&quot;);
        
        // Walk down tree to accumulate liquidity
        uint24 currentBase = 0;
        uint24 currentWidth = rootWidth;
        
        while (currentWidth &gt;= 1) {
            uint48 key = makeKey(currentBase, currentWidth);
            totalLiq += nodes[key].liquidity;
            
            if (currentWidth == 1) break;
            
            // Navigate to appropriate child
            uint24 midPoint = currentBase + currentWidth / 2;
            if (tick &lt; midPoint) {
                currentWidth /= 2;
            } else {
                currentBase = midPoint;
                currentWidth /= 2;
            }
        }
    }
    
    // Get node data at specific base and width
    function getNode(uint24 base, uint24 width) public view returns (TreeNode memory) {
        uint48 key = makeKey(base, width);
        return nodes[key];
    }
    
    // Helper function for testing - get root node
    function getRootNode() external view returns (TreeNode memory) {
        return getNode(0, rootWidth);
    }
    
    function findLCAWidth(uint24 left, uint24 right) internal pure returns (uint24) {
        if (left == right) return 1;
        uint24 diff = left ^ right;
        return msb(diff) &lt;&lt; 1; // Next power of 2
    }
    
    function min(uint24 a, uint24 b) internal pure returns (uint24) {
        return a &lt; b ? a : b;
    }
    
    function max(uint24 a, uint24 b) internal pure returns (uint24) {
        return a &gt; b ? a : b;
    }
    
    // Simple MSB function for demonstration
    function msb(uint24 x) internal pure returns (uint24 r) {
        if (x &gt;= 0x100) { x &gt;&gt;= 8; r += 8; }
        if (x &gt;= 0x10) { x &gt;&gt;= 4; r += 4; }
        if (x &gt;= 0x4) { x &gt;&gt;= 2; r += 2; }
        if (x &gt;= 0x2) r += 1;
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: MIT</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> ^0.8.0;</span>

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">AmmplifyTreeSimplified</span> </span>{
    <span class="hljs-keyword">struct</span> <span class="hljs-title">TreeNode</span> {
        <span class="hljs-keyword">uint24</span> base;        <span class="hljs-comment">// Starting tick</span>
        <span class="hljs-keyword">uint24</span> width;       <span class="hljs-comment">// Range width (power of 2)</span>
        <span class="hljs-keyword">uint128</span> liquidity;  <span class="hljs-comment">// Liquidity at this node</span>
        <span class="hljs-keyword">uint128</span> subtreeLiq; <span class="hljs-comment">// Total liquidity in subtree</span>
    }
    
    <span class="hljs-comment">// Tree storage: Key (base, width) -> Node data</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint48</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> TreeNode) <span class="hljs-keyword">public</span> nodes;
    <span class="hljs-keyword">uint24</span> <span class="hljs-keyword">public</span> rootWidth;
    
    <span class="hljs-comment">// Initialize the tree with a root width (must be power of 2)</span>
    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> _rootWidth</span>) </span>{
        <span class="hljs-built_in">require</span>(_rootWidth <span class="hljs-operator">></span> <span class="hljs-number">0</span> <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (_rootWidth <span class="hljs-operator">&#x26;</span> (_rootWidth <span class="hljs-operator">-</span> <span class="hljs-number">1</span>)) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>, <span class="hljs-string">"Root width must be power of 2"</span>);
        rootWidth <span class="hljs-operator">=</span> _rootWidth;
    }
    
    <span class="hljs-comment">// Create tree key from base and width</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">makeKey</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> base, <span class="hljs-keyword">uint24</span> width</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint48</span></span>) </span>{
        <span class="hljs-keyword">return</span> (<span class="hljs-keyword">uint48</span>(width) <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">&#x3C;</span> <span class="hljs-number">24</span>) <span class="hljs-operator">|</span> base;
    }
    
    <span class="hljs-comment">// Add liquidity to a range [left, right]</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addLiquidity</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> left, <span class="hljs-keyword">uint24</span> right, <span class="hljs-keyword">uint128</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> </span>{
        <span class="hljs-built_in">require</span>(left <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">=</span> right, <span class="hljs-string">"Invalid range"</span>);
        <span class="hljs-built_in">require</span>(right <span class="hljs-operator">&#x3C;</span> rootWidth, <span class="hljs-string">"Range exceeds tree bounds"</span>);
        
        <span class="hljs-comment">// Use simplified iterative approach</span>
        _updateRange(left, right, amount);
    }
    
    <span class="hljs-comment">// ITERATIVE tree walking (simplified Ammplify LCA approach)</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_updateRange</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> left, <span class="hljs-keyword">uint24</span> right, <span class="hljs-keyword">uint128</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> </span>{
        <span class="hljs-comment">// 1. Find LCA that contains the range (like real Ammplify)</span>
        <span class="hljs-keyword">uint24</span> lcaWidth <span class="hljs-operator">=</span> findLCAWidth(left, right);
        <span class="hljs-keyword">uint24</span> lcaBase <span class="hljs-operator">=</span> left <span class="hljs-operator">&#x26;</span> <span class="hljs-operator">~</span>(lcaWidth <span class="hljs-operator">-</span> <span class="hljs-number">1</span>);
        
        <span class="hljs-comment">// 2. Walk down from root to LCA, updating subtree totals</span>
        <span class="hljs-keyword">uint24</span> currentBase <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">uint24</span> currentWidth <span class="hljs-operator">=</span> rootWidth;
        
        <span class="hljs-keyword">while</span> (currentWidth <span class="hljs-operator">></span> lcaWidth) {
            <span class="hljs-keyword">uint48</span> key <span class="hljs-operator">=</span> makeKey(currentBase, currentWidth);
            nodes[key].subtreeLiq <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount <span class="hljs-operator">*</span> lcaWidth;  <span class="hljs-comment">// Width-weighted like Ammplify</span>
            
            <span class="hljs-comment">// Navigate toward LCA</span>
            <span class="hljs-keyword">uint24</span> midPoint <span class="hljs-operator">=</span> currentBase <span class="hljs-operator">+</span> currentWidth <span class="hljs-operator">/</span> <span class="hljs-number">2</span>;
            <span class="hljs-keyword">if</span> (lcaBase <span class="hljs-operator">&#x3C;</span> midPoint) {
                currentWidth <span class="hljs-operator">/</span><span class="hljs-operator">=</span> <span class="hljs-number">2</span>;  <span class="hljs-comment">// Go left</span>
            } <span class="hljs-keyword">else</span> {
                currentBase <span class="hljs-operator">=</span> midPoint;  <span class="hljs-comment">// Go right</span>
                currentWidth <span class="hljs-operator">/</span><span class="hljs-operator">=</span> <span class="hljs-number">2</span>;
            }
        }
        
        <span class="hljs-comment">// 3. Update the LCA node itself</span>
        <span class="hljs-keyword">uint48</span> lcaKey <span class="hljs-operator">=</span> makeKey(lcaBase, lcaWidth);
        nodes[lcaKey].subtreeLiq <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount <span class="hljs-operator">*</span> lcaWidth;
        
        <span class="hljs-comment">// 4. If LCA exactly matches our range, add direct liquidity</span>
        <span class="hljs-keyword">if</span> (lcaBase <span class="hljs-operator">=</span><span class="hljs-operator">=</span> left <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (lcaBase <span class="hljs-operator">+</span> lcaWidth <span class="hljs-operator">-</span> <span class="hljs-number">1</span>) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> right) {
            nodes[lcaKey].liquidity <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// 5. Otherwise, recursively update children (simplified)</span>
            _updateLCAChildren(lcaBase, lcaWidth, left, right, amount);
        }
    }
    
    <span class="hljs-comment">// Handle range updates within the LCA subtree</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">_updateLCAChildren</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> base, <span class="hljs-keyword">uint24</span> width, <span class="hljs-keyword">uint24</span> left, <span class="hljs-keyword">uint24</span> right, <span class="hljs-keyword">uint128</span> amount</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> </span>{
        <span class="hljs-keyword">if</span> (width <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>) {
            <span class="hljs-comment">// Leaf node - add direct liquidity</span>
            <span class="hljs-keyword">uint48</span> key <span class="hljs-operator">=</span> makeKey(base, width);
            nodes[key].liquidity <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
            <span class="hljs-keyword">return</span>;
        }
        
        <span class="hljs-keyword">uint24</span> midPoint <span class="hljs-operator">=</span> base <span class="hljs-operator">+</span> width <span class="hljs-operator">/</span> <span class="hljs-number">2</span>;
        <span class="hljs-keyword">uint24</span> leftWidth <span class="hljs-operator">=</span> width <span class="hljs-operator">/</span> <span class="hljs-number">2</span>;
        <span class="hljs-keyword">uint24</span> rightWidth <span class="hljs-operator">=</span> width <span class="hljs-operator">/</span> <span class="hljs-number">2</span>;
        
        <span class="hljs-comment">// Update left child if range overlaps</span>
        <span class="hljs-keyword">if</span> (left <span class="hljs-operator">&#x3C;</span> midPoint) {
            <span class="hljs-keyword">uint48</span> leftKey <span class="hljs-operator">=</span> makeKey(base, leftWidth);
            <span class="hljs-keyword">uint24</span> leftEnd <span class="hljs-operator">=</span> min(right, midPoint <span class="hljs-operator">-</span> <span class="hljs-number">1</span>);
            <span class="hljs-keyword">uint24</span> childAmount <span class="hljs-operator">=</span> (leftEnd <span class="hljs-operator">-</span> left <span class="hljs-operator">+</span> <span class="hljs-number">1</span>);
            nodes[leftKey].subtreeLiq <span class="hljs-operator">+</span><span class="hljs-operator">=</span> childAmount <span class="hljs-operator">*</span> amount;
            
            <span class="hljs-keyword">if</span> (base <span class="hljs-operator">=</span><span class="hljs-operator">=</span> left <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (base <span class="hljs-operator">+</span> leftWidth <span class="hljs-operator">-</span> <span class="hljs-number">1</span>) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> leftEnd) {
                nodes[leftKey].liquidity <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (leftWidth <span class="hljs-operator">></span> <span class="hljs-number">1</span>) {
                _updateLCAChildren(base, leftWidth, left, leftEnd, amount);
            }
        }
        
        <span class="hljs-comment">// Update right child if range overlaps  </span>
        <span class="hljs-keyword">if</span> (right <span class="hljs-operator">></span><span class="hljs-operator">=</span> midPoint) {
            <span class="hljs-keyword">uint48</span> rightKey <span class="hljs-operator">=</span> makeKey(midPoint, rightWidth);
            <span class="hljs-keyword">uint24</span> rightStart <span class="hljs-operator">=</span> max(left, midPoint);
            <span class="hljs-keyword">uint24</span> childAmount <span class="hljs-operator">=</span> (right <span class="hljs-operator">-</span> rightStart <span class="hljs-operator">+</span> <span class="hljs-number">1</span>);
            nodes[rightKey].subtreeLiq <span class="hljs-operator">+</span><span class="hljs-operator">=</span> childAmount <span class="hljs-operator">*</span> amount;
            
            <span class="hljs-keyword">if</span> (midPoint <span class="hljs-operator">=</span><span class="hljs-operator">=</span> rightStart <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> (midPoint <span class="hljs-operator">+</span> rightWidth <span class="hljs-operator">-</span> <span class="hljs-number">1</span>) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> right) {
                nodes[rightKey].liquidity <span class="hljs-operator">+</span><span class="hljs-operator">=</span> amount;
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (rightWidth <span class="hljs-operator">></span> <span class="hljs-number">1</span>) {
                _updateLCAChildren(midPoint, rightWidth, rightStart, right, amount);
            }
        }
    }
    
    <span class="hljs-comment">// Query liquidity at a specific tick</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getLiquidityAt</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> tick</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint128</span> totalLiq</span>) </span>{
        <span class="hljs-built_in">require</span>(tick <span class="hljs-operator">&#x3C;</span> rootWidth, <span class="hljs-string">"Tick out of bounds"</span>);
        
        <span class="hljs-comment">// Walk down tree to accumulate liquidity</span>
        <span class="hljs-keyword">uint24</span> currentBase <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;
        <span class="hljs-keyword">uint24</span> currentWidth <span class="hljs-operator">=</span> rootWidth;
        
        <span class="hljs-keyword">while</span> (currentWidth <span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>) {
            <span class="hljs-keyword">uint48</span> key <span class="hljs-operator">=</span> makeKey(currentBase, currentWidth);
            totalLiq <span class="hljs-operator">+</span><span class="hljs-operator">=</span> nodes[key].liquidity;
            
            <span class="hljs-keyword">if</span> (currentWidth <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>) <span class="hljs-keyword">break</span>;
            
            <span class="hljs-comment">// Navigate to appropriate child</span>
            <span class="hljs-keyword">uint24</span> midPoint <span class="hljs-operator">=</span> currentBase <span class="hljs-operator">+</span> currentWidth <span class="hljs-operator">/</span> <span class="hljs-number">2</span>;
            <span class="hljs-keyword">if</span> (tick <span class="hljs-operator">&#x3C;</span> midPoint) {
                currentWidth <span class="hljs-operator">/</span><span class="hljs-operator">=</span> <span class="hljs-number">2</span>;
            } <span class="hljs-keyword">else</span> {
                currentBase <span class="hljs-operator">=</span> midPoint;
                currentWidth <span class="hljs-operator">/</span><span class="hljs-operator">=</span> <span class="hljs-number">2</span>;
            }
        }
    }
    
    <span class="hljs-comment">// Get node data at specific base and width</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getNode</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> base, <span class="hljs-keyword">uint24</span> width</span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params">TreeNode <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">uint48</span> key <span class="hljs-operator">=</span> makeKey(base, width);
        <span class="hljs-keyword">return</span> nodes[key];
    }
    
    <span class="hljs-comment">// Helper function for testing - get root node</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRootNode</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params">TreeNode <span class="hljs-keyword">memory</span></span>) </span>{
        <span class="hljs-keyword">return</span> getNode(<span class="hljs-number">0</span>, rootWidth);
    }
    
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">findLCAWidth</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> left, <span class="hljs-keyword">uint24</span> right</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint24</span></span>) </span>{
        <span class="hljs-keyword">if</span> (left <span class="hljs-operator">=</span><span class="hljs-operator">=</span> right) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
        <span class="hljs-keyword">uint24</span> diff <span class="hljs-operator">=</span> left <span class="hljs-operator">^</span> right;
        <span class="hljs-keyword">return</span> msb(diff) <span class="hljs-operator">&#x3C;</span><span class="hljs-operator">&#x3C;</span> <span class="hljs-number">1</span>; <span class="hljs-comment">// Next power of 2</span>
    }
    
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">min</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> a, <span class="hljs-keyword">uint24</span> b</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint24</span></span>) </span>{
        <span class="hljs-keyword">return</span> a <span class="hljs-operator">&#x3C;</span> b ? a : b;
    }
    
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">max</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> a, <span class="hljs-keyword">uint24</span> b</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint24</span></span>) </span>{
        <span class="hljs-keyword">return</span> a <span class="hljs-operator">></span> b ? a : b;
    }
    
    <span class="hljs-comment">// Simple MSB function for demonstration</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">msb</span>(<span class="hljs-params"><span class="hljs-keyword">uint24</span> x</span>) <span class="hljs-title"><span class="hljs-keyword">internal</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint24</span> r</span>) </span>{
        <span class="hljs-keyword">if</span> (x <span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">0x100</span>) { x <span class="hljs-operator">></span><span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">8</span>; r <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-number">8</span>; }
        <span class="hljs-keyword">if</span> (x <span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">0x10</span>) { x <span class="hljs-operator">></span><span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">4</span>; r <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-number">4</span>; }
        <span class="hljs-keyword">if</span> (x <span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">0x4</span>) { x <span class="hljs-operator">></span><span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">2</span>; r <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-number">2</span>; }
        <span class="hljs-keyword">if</span> (x <span class="hljs-operator">></span><span class="hljs-operator">=</span> <span class="hljs-number">0x2</span>) r <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-number">1</span>;
    }
}
</code></pre><p>This is the basic structure of how the binary tree is represented in Ammplify and how range updates are facilitated through tree traversal. The actual implementation would be more complex, especially in terms of fee calculations and maker/taker interactions, but this gives a foundational understanding of the tree-based approach in the Ammplify protocol.</p><h2 id="h-real-world-usage" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Real-World Usage</h2><p>In production, Ammplify uses this tree system for:</p><ol><li><p><strong>Maker Operations</strong>: Adding/removing liquidity ranges efficiently</p></li><li><p><strong>Taker Operations</strong>: Borrowing liquidity against collateral</p></li><li><p><strong>Fee Distribution</strong>: Proportional fee sharing across tree nodes</p></li><li><p><strong>Price Discovery</strong>: Fast lookups for active liquidity at cthe urrent price</p></li><li><p><strong>Rebalancing</strong>: Moving liquidity between price ranges with minimal gas</p></li></ol><p>This binary tree architecture represents a fundamental evolution in AMM design, moving from linear tick processing to hierarchical range management, enabling new possibilities for capital efficiency and gas optimization in DeFi.</p>]]></content:encoded>
            <author>otor@newsletter.paragraph.com (otor)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/ee82a1c0ac0a8177550f77f7e7f3b856026f4886369819f830990d492a483f87.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>