<?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: Saurav Kumar</title>
    <description>The latest articles on Forem by Saurav Kumar (@sauravkumar8178).</description>
    <link>https://forem.com/sauravkumar8178</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%2F890583%2F928e350e-9a1d-46fc-b5fd-7ef242324389.jpeg</url>
      <title>Forem: Saurav Kumar</title>
      <link>https://forem.com/sauravkumar8178</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sauravkumar8178"/>
    <language>en</language>
    <item>
      <title>Beyond Function Calling: Introducing Advanced Tool Orchestration on the Claude Developer Platform</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Wed, 26 Nov 2025 05:09:17 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/beyond-function-calling-introducing-advanced-tool-orchestration-on-the-claude-developer-platform-5g69</link>
      <guid>https://forem.com/sauravkumar8178/beyond-function-calling-introducing-advanced-tool-orchestration-on-the-claude-developer-platform-5g69</guid>
      <description>&lt;p&gt;The future of AI agents relies on their ability to seamlessly and efficiently integrate with vast libraries of tools—from internal databases and company-specific APIs to public services like GitHub and Slack. As professional developers, we know that scaling an agent from five tools to fifty or five hundred introduces critical bottlenecks: context bloat, slow execution, and unpredictable tool invocation.&lt;/p&gt;

&lt;p&gt;To solve these challenges, we are excited to introduce three advanced features on the Claude Developer Platform that fundamentally change how agents discover, orchestrate, and utilize external capabilities. These features move Claude from simple sequential function calling to intelligent, programmatic orchestration.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Tool Search Tool: Dynamic Discovery for Infinite Scale
&lt;/h2&gt;

&lt;p&gt;When building agents that connect to many services (e.g., a five-server MCP setup with dozens of tools), token overhead quickly becomes a critical limitation.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge: Context Bloat and Accuracy
&lt;/h3&gt;

&lt;p&gt;Traditional tool use requires loading &lt;strong&gt;all&lt;/strong&gt; tool definitions into Claude's context window upfront. For a large multi-server environment (e.g., GitHub, Slack, Jira, Sentry, Splunk), tool schemas can easily consume &lt;strong&gt;50,000+ tokens&lt;/strong&gt; before the agent even begins its work. This limits space for conversation history and reasoning, increasing cost and reducing performance. Furthermore, overwhelming Claude with dozens of similar-sounding tool names leads to frequent selection errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: On-Demand Tool Discovery
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Tool Search Tool&lt;/strong&gt; solves this by letting Claude discover and load tools only when they are needed for the current task.&lt;/p&gt;

&lt;p&gt;Developers mark less-critical tools with &lt;code&gt;defer_loading: true&lt;/code&gt; in the API call. Claude initially only sees the lightweight Tool Search Tool itself and any frequently-used tools. When Claude determines it needs a specific capability (e.g., "create a pull request"), it searches the tool definitions, and only the relevant tools (e.g., &lt;code&gt;github.createPullRequest&lt;/code&gt;) are loaded into the context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-Life Use Case and Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Massive Token Savings:&lt;/strong&gt; In internal testing, this feature resulted in an &lt;strong&gt;85% reduction in token usage&lt;/strong&gt; on average compared to the traditional approach, preserving hundreds of thousands of tokens for reasoning and history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Accuracy at Scale:&lt;/strong&gt; By only presenting Claude with the most relevant tools, selection accuracy significantly improves, especially when dealing with large tool libraries. Internal benchmarks showed accuracy improvements from &lt;strong&gt;79.5% to 88.1%&lt;/strong&gt; on complex, multi-server evaluations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale Without Cost:&lt;/strong&gt; You can now connect your agent to hundreds of tools across dozens of microservices (e.g., a vast internal API ecosystem) without incurring a massive token penalty on every request.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Programmatic Tool Calling (PTC): Efficient Code Orchestration
&lt;/h2&gt;

&lt;p&gt;For complex, multi-step workflows involving data processing, the traditional method of making sequential tool calls—with each result returning to Claude's context—is slow and inefficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge: Context Pollution and Inference Overhead
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Context Pollution:&lt;/strong&gt; When processing large data (e.g., 10MB log file analysis or retrieving 2,000+ expense line items), the raw, intermediate results flood Claude’s context window. This pushes out critical information and forces Claude to use precious context space for raw data processing, rather than high-level reasoning.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Inference Overhead:&lt;/strong&gt; Each tool call requires a full API round-trip and a new model inference pass to process the result and decide the next step. A 5-tool workflow involves 5 inference passes, leading to high latency.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Solution: Code-Driven Execution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Programmatic Tool Calling&lt;/strong&gt; enables Claude to orchestrate complex operations by writing a Python script that runs in a sandboxed execution environment. Instead of the model seeing all intermediate results, the script handles the logic: loops, conditionals, data transformations, and parallel execution.&lt;/p&gt;

&lt;p&gt;The script calls your tools (&lt;code&gt;get_team_members&lt;/code&gt;, &lt;code&gt;get_expenses&lt;/code&gt;, etc.), and the results are routed directly to the running code environment, &lt;strong&gt;bypassing Claude's context window&lt;/strong&gt;. Only the final, processed output from the script is returned to Claude for the final response generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-Life Use Case and Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Budget Compliance Check:&lt;/strong&gt; Imagine determining which team members exceeded their Q3 travel budget. PTC allows Claude to write a script that:

&lt;ol&gt;
&lt;li&gt; Fetches team members and budgets in parallel.&lt;/li&gt;
&lt;li&gt; Fetches all expense line items (e.g., 2,000 records).&lt;/li&gt;
&lt;li&gt; Sums the expenses, compares them to the budget limit, and filters the results—all within the code sandbox.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Claude only sees the final list&lt;/strong&gt; of the 2-3 members who exceeded their budget, reducing context consumption from &lt;strong&gt;~200KB of raw data to ~1KB of results&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced Latency:&lt;/strong&gt; By orchestrating multiple tool calls within a single execution block, you &lt;strong&gt;eliminate most inference passes&lt;/strong&gt; (e.g., 19+ passes saved in a 20-tool workflow), leading to significant latency improvements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token &amp;amp; Accuracy Gains:&lt;/strong&gt; Internal testing showed a &lt;strong&gt;37% reduction in token consumption&lt;/strong&gt; on complex research tasks and improved accuracy (e.g., GIA benchmarks improved from 46.5% to 51.2%) due to explicit, programmatic control flow.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Tool Use Examples: Defining Usage Patterns for Reliability
&lt;/h2&gt;

&lt;p&gt;JSON Schema is necessary for defining the structural requirements of a tool, but it's often insufficient for defining how the tool &lt;em&gt;should&lt;/em&gt; be used in practice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Challenge: Ambiguity and Parameter Errors
&lt;/h3&gt;

&lt;p&gt;Schema cannot express critical usage conventions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Format Ambiguity:&lt;/strong&gt; What date format should &lt;code&gt;due_date&lt;/code&gt; use (&lt;code&gt;YYYY-MM-DD&lt;/code&gt; vs. &lt;code&gt;MM/DD/YYYY&lt;/code&gt;)?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correlated Parameters:&lt;/strong&gt; How do &lt;code&gt;priority&lt;/code&gt; level and &lt;code&gt;escalation.sla_hours&lt;/code&gt; relate?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage Conventions:&lt;/strong&gt; When should optional, nested structures like &lt;code&gt;reporter.contact&lt;/code&gt; be included?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These ambiguities are a primary source of malformed tool calls and inconsistent agent behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: Concrete Usage Demonstration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tool Use Examples&lt;/strong&gt; allow you to include one or more concrete, successful tool invocation objects (&lt;code&gt;input_examples&lt;/code&gt;) directly in your tool definition.&lt;/p&gt;

&lt;p&gt;By providing examples of successful calls—including a minimal call, a partial call, and a full, complex call—you demonstrate the API's expected behavior and conventions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-Life Use Case and Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Consistency:&lt;/strong&gt; For a complex &lt;code&gt;create_ticket&lt;/code&gt; API, examples can teach Claude:

&lt;ul&gt;
&lt;li&gt;To use "YYYY-MM-DD" for dates.&lt;/li&gt;
&lt;li&gt;To follow a specific ID convention (e.g., "USR-12345").&lt;/li&gt;
&lt;li&gt;That &lt;code&gt;critical&lt;/code&gt; priority always requires populating the full &lt;code&gt;escalation&lt;/code&gt; object.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Increased Reliability:&lt;/strong&gt; Claude learns the "intent" behind the schema, leading to more reliable and consistent parameter population, especially for optional fields and nested objects.&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Strategic Layering for Optimal Agent Architecture
&lt;/h2&gt;

&lt;p&gt;These three features are designed to be complementary, allowing you to layer them strategically to solve your specific agent bottlenecks:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bottleneck&lt;/th&gt;
&lt;th&gt;Feature to Use&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Context bloat&lt;/strong&gt; from tool definitions&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tool Search Tool&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Dynamic discovery&lt;/strong&gt; preserves context and improves accuracy at scale.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Large intermediate results&lt;/strong&gt; polluting context&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Programmatic Tool Calling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Code orchestration&lt;/strong&gt; ensures only actionable final results enter context.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Parameter errors&lt;/strong&gt; and malformed calls&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tool Use Examples&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Demonstrates usage patterns&lt;/strong&gt; for reliable and consistent invocation.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By adopting dynamic discovery, code-based orchestration, and usage-pattern learning, you can build truly scalable, accurate, and efficient AI agents capable of mastering even the most complex enterprise workflows. These features are available today in beta for professional developers.&lt;/p&gt;




&lt;p&gt;For more technical details and implementation guides, you can read the original article: &lt;a href="https://www.anthropic.com/engineering/advanced-tool-use" rel="noopener noreferrer"&gt;Introducing advanced tool use on the Claude Developer Platform&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>llm</category>
      <category>ai</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Maximizing WebAI Performance: A Deep Dive into LiteRT.js</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Mon, 24 Nov 2025 03:39:21 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/maximizing-webai-performance-a-deep-dive-into-litertjs-5od</link>
      <guid>https://forem.com/sauravkumar8178/maximizing-webai-performance-a-deep-dive-into-litertjs-5od</guid>
      <description>&lt;p&gt;The landscape of client-side machine learning is shifting. For years, deploying high-performance models in the browser meant navigating a complex maze of converters, polyfills, and performance bottlenecks. Enter &lt;strong&gt;LiteRT.js&lt;/strong&gt;—Google's newly branded, high-performance WebAI runtime designed specifically for production web applications.&lt;/p&gt;

&lt;p&gt;If you are a professional developer looking to run PyTorch, JAX, or TensorFlow models directly in the browser with near-native speeds, this is the runtime you've been waiting for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is LiteRT for Web?
&lt;/h2&gt;

&lt;p&gt;LiteRT (formerly TensorFlow Lite) has long been the standard for on-device ML on Android and iOS. &lt;strong&gt;LiteRT.js&lt;/strong&gt; extends this unified runtime to the web. It is not just a wrapper; it is a purpose-built runtime that leverages &lt;strong&gt;WebGPU&lt;/strong&gt; for massive parallel compute capabilities and &lt;strong&gt;WebAssembly (Wasm)&lt;/strong&gt; with XNNPack for optimized CPU execution.&lt;/p&gt;

&lt;p&gt;For professional engineers, the value proposition is clear: &lt;strong&gt;Unified architecture.&lt;/strong&gt; The same &lt;code&gt;.tflite&lt;/code&gt; model you deploy on Android can now be dropped into your web app, ensuring consistent behavior across platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Features for Production Apps
&lt;/h2&gt;

&lt;p&gt;LiteRT.js brings a suite of features strictly targeted at solving "real-life" production constraints:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Best-in-Class Hardware Acceleration
&lt;/h3&gt;

&lt;p&gt;LiteRT.js is built to squeeze every drop of performance from the user's device:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WebGPU Support:&lt;/strong&gt; Leverages the modern WebGPU API for high-throughput parallel processing, significantly outperforming legacy WebGL backends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;XNNPack on Wasm:&lt;/strong&gt; For devices without powerful GPUs, it falls back to highly optimized CPU inference using XNNPack instructions via WebAssembly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Multi-Framework Compatibility
&lt;/h3&gt;

&lt;p&gt;The days of being locked into a single framework for web deployment are over. LiteRT.js supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PyTorch:&lt;/strong&gt; Direct conversion path to LiteRT (skipping the brittle ONNX -&amp;gt; TF -&amp;gt; TF.js chain).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JAX &amp;amp; TensorFlow:&lt;/strong&gt; Full support for models exported to the standard &lt;code&gt;.tflite&lt;/code&gt; flatbuffer format.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Seamless TensorFlow.js Interoperability
&lt;/h3&gt;

&lt;p&gt;If you have an existing TF.js pipeline (e.g., for pre/post-processing), you don't need to rewrite it. LiteRT.js creates a bridge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accepts &lt;strong&gt;TensorFlow.js Tensors&lt;/strong&gt; as inputs.&lt;/li&gt;
&lt;li&gt;Outputs &lt;strong&gt;TensorFlow.js Tensors&lt;/strong&gt; for downstream tasks.&lt;/li&gt;
&lt;li&gt;Allows you to swap &lt;em&gt;only&lt;/em&gt; the inference engine while keeping your data plumbing intact.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Technical Deep Dive: Implementation
&lt;/h2&gt;

&lt;p&gt;Let's look at how to implement this in a real-world TypeScript/JavaScript environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Installation &amp;amp; Setup
&lt;/h3&gt;

&lt;p&gt;You need the core package. You also need to serve the Wasm binaries statically so the browser can fetch them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @litertjs/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Running a Model (The "Hot Path")
&lt;/h3&gt;

&lt;p&gt;Here is a pattern for loading a model and running inference using the WebGPU backend. This is critical for latency-sensitive apps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadAndCompile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Tensor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@litertjs/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Initialize the runtime&lt;/span&gt;
&lt;span class="c1"&gt;// Ensure you host the 'wasm' folder from node_modules on your server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;loadAndCompile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/models/object_detection.tflite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;accelerator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webgpu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Force WebGPU for max speed&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Prepare Input Data&lt;/span&gt;
&lt;span class="c1"&gt;// Imagine this comes from an HTMLCanvasElement or Video stream&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rawData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Float32Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;224&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

&lt;span class="c1"&gt;// 3. Create Tensor &amp;amp; Move to GPU Memory&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputTensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;moveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webgpu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 4. Inference&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&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="nx"&gt;inputTensor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 5. Retrieve Results&lt;/span&gt;
&lt;span class="c1"&gt;// Move memory back to CPU only when you need to read it&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultTensor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;moveTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wasm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resultTensor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toTypedArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// 6. Cleanup (Crucial for long-running apps!)&lt;/span&gt;
&lt;span class="nx"&gt;inputTensor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;resultTensor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: The PyTorch Conversion Workflow
&lt;/h3&gt;

&lt;p&gt;One of the strongest features is the direct conversion. You no longer need to debug intermediate ONNX failures.&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;ai_edge_torch&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torchvision&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;

&lt;span class="c1"&gt;# Load a standard PyTorch model
&lt;/span&gt;&lt;span class="n"&gt;resnet18&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torchvision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resnet18&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;torchvision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResNet18_Weights&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IMAGENET1K_V1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sample_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;224&lt;/span&gt;&lt;span class="p"&gt;),)&lt;/span&gt;

&lt;span class="c1"&gt;# Convert directly to LiteRT (.tflite)
&lt;/span&gt;&lt;span class="n"&gt;edge_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ai_edge_torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resnet18&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;sample_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;edge_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;resnet18_web.tflite&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-Life Use Cases for Professional Developers
&lt;/h2&gt;

&lt;p&gt;Why switch to LiteRT.js? Here are three concrete scenarios where this runtime provides a business advantage:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Privacy-Preserving Document Processing (FinTech/Legal)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; A user needs to upload a sensitive ID document (Passport/Driver's License) for KYC verification.&lt;br&gt;
&lt;strong&gt;The LiteRT.js Solution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case:&lt;/strong&gt; Run an OCR and object detection model (like EfficientDet) entirely in the client's browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benefit:&lt;/strong&gt; Zero data leaves the device. You redact PII (Personally Identifiable Information) locally before the image is ever uploaded to your server. This drastically simplifies GDPR/HIPAA compliance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Real-Time Video Conferencing Tools
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Building a custom video platform that requires virtual backgrounds or "low-light mode" correction.&lt;br&gt;
&lt;strong&gt;The LiteRT.js Solution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case:&lt;/strong&gt; Apply a segmentation model (e.g., DeepLabV3) to every frame of a video stream (30fps).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benefit:&lt;/strong&gt; The &lt;strong&gt;WebGPU backend&lt;/strong&gt; is essential here. WebGL often chokes on high-resolution segmentation, but LiteRT.js leverages modern GPU compute shaders to process frames in under 16ms, ensuring no lag in the video feed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Offline-First Field Applications
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; An iPad app for agricultural inspectors analyzing crop disease in remote fields with poor 4G/5G.&lt;br&gt;
&lt;strong&gt;The LiteRT.js Solution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case:&lt;/strong&gt; Run complex vision models to classify crop health instantly without a server round-trip.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Benefit:&lt;/strong&gt; By using the standard &lt;code&gt;.tflite&lt;/code&gt; format, you can use the exact same model file for the Web app (LiteRT.js) and the native Android/iOS app versions, reducing your MLOps maintenance burden by 50%.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Resources
&lt;/h2&gt;

&lt;p&gt;Ready to ship? Use these official resources to fast-track your development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://goo.gle/47tIuNH" rel="noopener noreferrer"&gt;LiteRT Web Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://goo.gle/4oo3201" rel="noopener noreferrer"&gt;LiteRT Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPM:&lt;/strong&gt; &lt;a href="https://goo.gle/47LLvb1" rel="noopener noreferrer"&gt;@litertjs/core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=HAjotVloAvI" rel="noopener noreferrer"&gt;LiteRT.js: Google's High Performance WebAI Runtime&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>litert</category>
      <category>googlecloud</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🚀 Experience Liftoff: Google Antigravity—The Agent-First IDE Redefining Development</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Thu, 20 Nov 2025 04:00:41 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/experience-liftoff-google-antigravity-the-agent-first-ide-redefining-development-55oe</link>
      <guid>https://forem.com/sauravkumar8178/experience-liftoff-google-antigravity-the-agent-first-ide-redefining-development-55oe</guid>
      <description>&lt;p&gt;The age of the simple AI "autocomplete" is over. We've entered the era of the &lt;strong&gt;Agent-First&lt;/strong&gt; IDE, and Google's &lt;strong&gt;Antigravity&lt;/strong&gt; is leading the charge. Launched alongside the powerful Gemini 3 model, Antigravity is not just a souped-up VS Code fork; it's a completely new paradigm where AI agents function as autonomous, accountable teammates, operating across your entire development workflow.&lt;/p&gt;

&lt;p&gt;For the professional software developer, Antigravity shifts your role from line-by-line implementation to &lt;strong&gt;high-level architecture and task delegation&lt;/strong&gt;. It elevates human judgment by automating the tedious execution, fundamentally changing how fast, and how far, a single engineer can build.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Innovation: Autonomous Agents in Mission Control
&lt;/h2&gt;

&lt;p&gt;Antigravity's biggest differentiator is the shift from an AI assistant that only gives suggestions, to an &lt;strong&gt;AI Agent&lt;/strong&gt; that can autonomously plan, execute, and verify complex tasks across multiple surfaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cross-Surface Agentic Control
&lt;/h3&gt;

&lt;p&gt;Your agents are no longer confined to the chat panel. They can operate synchronously across the three core development surfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code Editor:&lt;/strong&gt; Writing, refactoring, and fixing code directly in your files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terminal:&lt;/strong&gt; Installing dependencies, running build commands, and debugging tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browser:&lt;/strong&gt; Running the application, navigating user flows, and visually verifying the output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-Life Use:&lt;/strong&gt; Instead of manually running the steps to fix a bug, your task is now: "Fix the layout bug on the mobile checkout page, run a local test, and ensure the change doesn't break the desktop view." The agent takes over, edits files, runs the server, drives the integrated browser, and provides a final, verifiable result. &lt;/p&gt;




&lt;h3&gt;
  
  
  2. Artifacts for Trust and Transparency
&lt;/h3&gt;

&lt;p&gt;Autonomous agents can feel like a black box. Antigravity solves this with &lt;strong&gt;Artifacts&lt;/strong&gt;—structured, verifiable deliverables that replace overwhelming log files with human-readable documentation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Artifact Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Real-Life Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Implementation Plan&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A detailed, step-by-step proposal before code is written.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Reviewing Architecture:&lt;/strong&gt; An agent proposes a full plan for a multi-file refactor. You review the plan, adjust the strategy, and approve before a single line is changed, ensuring architectural alignment.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Browser Recording&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A video walkthrough of the agent interacting with the live application.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;End-to-End Testing:&lt;/strong&gt; An agent performs a full user flow (e.g., login, add to cart, checkout) and provides a recorded, verifiable proof that the new feature works as intended.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code Diffs &amp;amp; Summaries&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clear, organized summaries of all file changes and the agent's reasoning.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;PR Generation:&lt;/strong&gt; Automatically generates a comprehensive pull request description and links the verification artifacts, drastically accelerating code review time.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  3. Dual-View Workflow: Editor and Manager View
&lt;/h3&gt;

&lt;p&gt;Antigravity provides two distinct interfaces, catering to different modes of development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Editor View:&lt;/strong&gt; The familiar, VS Code-like experience with an integrated agent sidebar for immediate, context-aware assistance and code completions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manager View ("Mission Control"):&lt;/strong&gt; A central hub for orchestrating &lt;strong&gt;multiple agents&lt;/strong&gt; across separate projects or tasks simultaneously. This is where you operate as an architect and project manager.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-Life Use:&lt;/strong&gt; You can delegate a task to a &lt;strong&gt;Refactoring Agent&lt;/strong&gt; to clean up a legacy service while you use the Editor View to implement a new feature. You check the Refactoring Agent's progress and artifacts asynchronously in the Manager View, parallelizing work that previously required constant context-switching.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔑 Key Features and Capabilities
&lt;/h2&gt;

&lt;p&gt;Antigravity, built on the open-source base of VS Code, layers on several powerful agentic features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Model Support:&lt;/strong&gt; While powered by &lt;strong&gt;Gemini 3 Pro&lt;/strong&gt;, the platform is not locked to one vendor. You can select models like &lt;strong&gt;Claude Sonnet 4.5&lt;/strong&gt; or &lt;strong&gt;GPT-OSS&lt;/strong&gt; to power your agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in Self-Improvement:&lt;/strong&gt; Agents can learn from past projects, saving successful code snippets, task execution patterns, and architectural decisions to an internal knowledge base, making them more effective over time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrated Feedback Loop:&lt;/strong&gt; You can add Google Docs-style comments directly onto artifacts (like screenshots or task plans) to redirect the agent without stopping the current run, ensuring continuous feedback and refinement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Context Protocol (MCP):&lt;/strong&gt; This powerful feature allows the agent to securely connect to external tools and data sources like &lt;strong&gt;GitHub&lt;/strong&gt;, &lt;strong&gt;Linear&lt;/strong&gt;, &lt;strong&gt;Notion&lt;/strong&gt;, and live databases (e.g., &lt;strong&gt;MongoDB&lt;/strong&gt; or &lt;strong&gt;Supabase&lt;/strong&gt;), allowing it to read real-time schemas, logs, and external documentation without manual copy-paste.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Elevating the Developer's Role: Practical Use Cases
&lt;/h2&gt;

&lt;p&gt;Antigravity fundamentally changes the types of tasks professional developers will focus on. You become the &lt;strong&gt;Architect&lt;/strong&gt; and &lt;strong&gt;Reviewer&lt;/strong&gt;, while the agents handle the execution.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Antigravity Agent Action&lt;/th&gt;
&lt;th&gt;Developer Focus Shift&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Feature Prototyping&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Takes a natural language prompt ("Build a responsive dashboard component that shows real-time user metrics.") and scaffolds the entire front-end and back-end logic.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;From:&lt;/strong&gt; Writing boilerplate and setting up dependencies. &lt;strong&gt;To:&lt;/strong&gt; Defining the high-level API contract and UX goals.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Legacy Code Refactoring&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Analyzes a large, multi-file codebase, identifies anti-patterns, plans a refactoring strategy, executes the changes, and verifies backward compatibility with tests.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;From:&lt;/strong&gt; Manual, high-risk refactoring efforts. &lt;strong&gt;To:&lt;/strong&gt; Reviewing the agent's risk assessment and validating the architectural decision.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bug Diagnosis &amp;amp; Fix&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reproduces a reported bug using browser automation, analyzes error logs, identifies the root cause, proposes a code fix, validates the fix with automated testing, and updates documentation.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;From:&lt;/strong&gt; Spending hours reproducing and debugging. &lt;strong&gt;To:&lt;/strong&gt; Reviewing the agent's diagnosis and approving the change.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Integration Testing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uses the &lt;strong&gt;MCP&lt;/strong&gt; to pull a live API schema from a database, generates mock servers, and writes a full suite of integration tests that validate all endpoint responses against the schema.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;From:&lt;/strong&gt; Writing tedious test boilerplate and mock data. &lt;strong&gt;To:&lt;/strong&gt; Defining the test coverage requirements and reviewing the quality of the generated tests.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Google Antigravity is a declaration that the future of coding is &lt;strong&gt;agentic&lt;/strong&gt;. By granting agents autonomy and accountability through the Artifact system, it enables developers to achieve unprecedented velocity, lifting the entire software development process to a higher, more strategic altitude.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⬇️ Get Started with Antigravity Today
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ready to experience liftoff?&lt;/strong&gt; The public preview is available for all major desktop platforms.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Official Website:&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://antigravity.google/" rel="noopener noreferrer"&gt;antigravity.google&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct Download Page:&lt;/strong&gt; &lt;strong&gt;&lt;a href="https://antigravity.google/download" rel="noopener noreferrer"&gt;antigravity.google/download&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The public preview is available at no charge and is compatible with &lt;strong&gt;macOS&lt;/strong&gt;, &lt;strong&gt;Windows&lt;/strong&gt;, and &lt;strong&gt;Linux&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>antigravity</category>
      <category>ai</category>
      <category>gemini</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>🚀 Exploring Kwala: The No-Code Powerhouse for Blockchain Backend Automation</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Tue, 04 Nov 2025 05:47:14 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/exploring-kwala-the-no-code-powerhouse-for-blockchain-backend-automation-3db6</link>
      <guid>https://forem.com/sauravkumar8178/exploring-kwala-the-no-code-powerhouse-for-blockchain-backend-automation-3db6</guid>
      <description>&lt;p&gt;When I joined the &lt;strong&gt;Kwala Hacker House Hackathon&lt;/strong&gt;, I had no idea that one tool would completely change the way I thought about building blockchain projects — &lt;strong&gt;Kwala&lt;/strong&gt;. Over an intense &lt;strong&gt;8-hour hackathon&lt;/strong&gt;, my team built &lt;strong&gt;Audifi&lt;/strong&gt;, an AI-powered tool that analyzes smart contracts, finds vulnerabilities, and generates automated test cases.&lt;/p&gt;

&lt;p&gt;But the real magic happened when we discovered how &lt;strong&gt;Kwala&lt;/strong&gt; could automate our blockchain backend within minutes — without a single line of server code.&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%2Fi0.wp.com%2Fwww.javaadvent.com%2Fcontent%2Fuploads%2F2022%2F12%2F174335482-9e2744e4-332d-490d-9427-6b5ee7d66100.png%3Ffit%3D1240%252C865%26ssl%3D1" 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%2Fi0.wp.com%2Fwww.javaadvent.com%2Fcontent%2Fuploads%2F2022%2F12%2F174335482-9e2744e4-332d-490d-9427-6b5ee7d66100.png%3Ffit%3D1240%252C865%26ssl%3D1" alt="Image" width="1240" height="865"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Introduction
&lt;/h2&gt;

&lt;p&gt;In the Web3 world, building smart contracts and front-ends is only half the story. The &lt;em&gt;backend logic&lt;/em&gt; — monitoring blockchain events, orchestrating state changes, scheduling tasks, calling APIs — often becomes the bottleneck.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;Kwala&lt;/strong&gt; steps in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kwala&lt;/strong&gt; allows developers to build &lt;strong&gt;automation and backend workflows for Web3 applications&lt;/strong&gt; without worrying about servers, polling scripts, or DevOps overhead. You simply define &lt;em&gt;what should happen&lt;/em&gt; — and Kwala executes it reliably across chains.&lt;/p&gt;

&lt;p&gt;In this article, let’s explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What Kwala is&lt;/li&gt;
&lt;li&gt;How it works under the hood&lt;/li&gt;
&lt;li&gt;Key features and use-cases&lt;/li&gt;
&lt;li&gt;Why developers love it&lt;/li&gt;
&lt;li&gt;And my experience using it during the hackathon&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚙️ What is Kwala?
&lt;/h2&gt;

&lt;p&gt;At its core, &lt;strong&gt;Kwala&lt;/strong&gt; is a &lt;strong&gt;verifiable Web3 workflow automation platform&lt;/strong&gt; — your programmable backend for decentralized applications.&lt;/p&gt;

&lt;p&gt;You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define your &lt;strong&gt;backend logic using YAML workflows&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Trigger &lt;strong&gt;smart contracts&lt;/strong&gt;, call &lt;strong&gt;APIs&lt;/strong&gt;, or listen to &lt;strong&gt;on-chain events&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Deploy it without any server or DevOps setup&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🏷️ &lt;em&gt;Tagline:&lt;/em&gt; “Your programmable Web3 backend — no servers, no DevOps, no infra bloat.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Kwala is designed for the &lt;strong&gt;multi-chain world&lt;/strong&gt;, making it easier for developers to connect decentralized systems without managing backend infrastructure.&lt;/p&gt;

&lt;p&gt;🌐 Learn more: &lt;a href="https://kwala.network" rel="noopener noreferrer"&gt;Kwala Network&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ How Kwala Works — Developer Flow &amp;amp; Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffn60b3udozsznsv3b136.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%2Ffn60b3udozsznsv3b136.png" alt="Image" width="800" height="938"&gt;&lt;/a&gt;&lt;br&gt;
Here’s how you can integrate Kwala into your project:&lt;/p&gt;

&lt;h3&gt;
  
  
  👩‍💻 Developer Workflow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Define a Workflow in YAML&lt;/strong&gt;
You create a &lt;code&gt;.yaml&lt;/code&gt; file that declares what triggers your logic and what happens next:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;   &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;contract.deployed&lt;/span&gt;
   &lt;span class="na"&gt;do&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;analyzeContract&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;generateTestCases&lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;notifyTeam&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of writing complex backend code, you describe &lt;em&gt;what you want&lt;/em&gt;, not &lt;em&gt;how to do it&lt;/em&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deploy the Workflow&lt;/strong&gt;&lt;br&gt;
Use Kwala’s dashboard or CLI to deploy your YAML definition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Runtime Execution&lt;/strong&gt;&lt;br&gt;
When the event fires (like a contract deployment), Kwala’s execution engine triggers the defined actions — calling smart contracts, APIs, or any automation you defined.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitor &amp;amp; Audit&lt;/strong&gt;&lt;br&gt;
You get detailed logs, execution reports, and verifiable trails — vital for Web3 transparency.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  🧱 Under the Hood
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trigger Layer&lt;/strong&gt; – Listens for on-chain or off-chain events&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution Engine&lt;/strong&gt; – Executes defined actions reliably&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validator Nodes&lt;/strong&gt; – Maintain decentralized execution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infra Abstraction&lt;/strong&gt; – No need for servers, scripts, or polling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Chain Flexibility&lt;/strong&gt; – Works seamlessly across EVM-compatible networks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essentially, Kwala turns your YAML files into &lt;strong&gt;living backend systems&lt;/strong&gt; that run autonomously.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 Key Features
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Declarative YAML Workflows&lt;/strong&gt; – Define your logic clearly, with no backend code&lt;br&gt;
✅ &lt;strong&gt;Event-Driven Architecture&lt;/strong&gt; – React to blockchain events or API triggers&lt;br&gt;
✅ &lt;strong&gt;Cross-Chain Automation&lt;/strong&gt; – One workflow for multiple networks&lt;br&gt;
✅ &lt;strong&gt;API &amp;amp; Smart Contract Integration&lt;/strong&gt; – Connect on-chain and off-chain worlds&lt;br&gt;
✅ &lt;strong&gt;Verifiable &amp;amp; Auditable&lt;/strong&gt; – Execution logs ensure trust and transparency&lt;br&gt;
✅ &lt;strong&gt;No Infrastructure Needed&lt;/strong&gt; – No servers, databases, or cron jobs&lt;br&gt;
✅ &lt;strong&gt;Perfect for MVPs &amp;amp; Hackathons&lt;/strong&gt; – Rapid iteration with zero infra setup&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Use Cases
&lt;/h2&gt;

&lt;p&gt;Here are some scenarios where Kwala truly shines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated DeFi Monitoring&lt;/strong&gt; – Trigger actions when price ratios change&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NFT Event Automation&lt;/strong&gt; – When NFT is minted, call APIs or send rewards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Chain Transactions&lt;/strong&gt; – Event on Chain A triggers logic on Chain B&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compliance &amp;amp; Audit Workflows&lt;/strong&gt; – Maintain verifiable event trails&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hackathons &amp;amp; Prototyping&lt;/strong&gt; – Build production-like backends in hours&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During the &lt;strong&gt;Kwala Hacker House Hackathon&lt;/strong&gt;, we leveraged it to automate complex blockchain monitoring flows — which would otherwise have required days of backend work.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ My Experience at Kwala Hacker House Hackathon
&lt;/h2&gt;

&lt;p&gt;At the hackathon, we were challenged to use &lt;strong&gt;Kwala&lt;/strong&gt; as part of our build. At first, I wasn’t sure how it would fit in — but within minutes, I realized its power.&lt;/p&gt;

&lt;p&gt;In our project &lt;strong&gt;Audifi&lt;/strong&gt;, we used Kwala to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Listen to &lt;strong&gt;contract deployment events&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Trigger our &lt;strong&gt;AI-based analysis pipeline&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Store &lt;strong&gt;detected vulnerabilities&lt;/strong&gt; automatically in the database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What usually takes hours of backend setup was done &lt;strong&gt;in minutes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For an 8-hour hackathon, Kwala made a real difference — turning our prototype into a functioning, automated blockchain system.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Why Developers Should Care
&lt;/h2&gt;

&lt;p&gt;Here’s why Kwala matters to Web3 builders:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;⚙️ No Backend Hassle&lt;/td&gt;
&lt;td&gt;Eliminate server setup, cron jobs, and infrastructure headaches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🚀 Faster Builds&lt;/td&gt;
&lt;td&gt;Go from idea to working backend in hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🌐 Multi-Chain Ready&lt;/td&gt;
&lt;td&gt;Works across multiple blockchain ecosystems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔒 Verifiable &amp;amp; Transparent&lt;/td&gt;
&lt;td&gt;Every execution can be audited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;💰 Cost-Efficient&lt;/td&gt;
&lt;td&gt;Pay only for workflows, not servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧩 Easy Integration&lt;/td&gt;
&lt;td&gt;Connects smart contracts and APIs seamlessly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Whether you’re a solo developer or a startup building on-chain infrastructure, Kwala accelerates your workflow automation journey.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧭 Getting Started with Kwala
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Visit:&lt;/strong&gt; &lt;a href="https://kwala.network" rel="noopener noreferrer"&gt;https://kwala.network&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore the Docs&lt;/strong&gt; – Learn the YAML structure for defining workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write a Simple Workflow&lt;/strong&gt; – Start with “on event → do actions” logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy to the Playground&lt;/strong&gt; – Test and refine your automation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale Up&lt;/strong&gt; – Add multi-chain or AI-driven logic as needed&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚖️ Pros &amp;amp; Cons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;✅ Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure-free backend automation&lt;/li&gt;
&lt;li&gt;Declarative, simple, and scalable&lt;/li&gt;
&lt;li&gt;Perfect for hackathons, MVPs, and DeFi automation&lt;/li&gt;
&lt;li&gt;Transparent, verifiable execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires learning YAML syntax&lt;/li&gt;
&lt;li&gt;Some limits in customization for complex logic&lt;/li&gt;
&lt;li&gt;Depends on Kwala’s availability and network reliability&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔮 The Future of Web3 Backends
&lt;/h2&gt;

&lt;p&gt;Kwala represents a shift from &lt;em&gt;Backend as Code&lt;/em&gt; to &lt;strong&gt;Backend as Workflow&lt;/strong&gt;.&lt;br&gt;
As Web3 grows, developers will demand faster, auditable, and multi-chain-ready automation tools — exactly where Kwala shines.&lt;/p&gt;

&lt;p&gt;Expect to see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-powered workflow recommendations&lt;/li&gt;
&lt;li&gt;Pre-built automation templates&lt;/li&gt;
&lt;li&gt;Deeper integrations with DeFi and NFT ecosystems&lt;/li&gt;
&lt;li&gt;Wider support for non-EVM chains&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;If you’re a &lt;strong&gt;Web3 developer, startup, or hackathon builder&lt;/strong&gt;, it’s time to rethink how you handle your backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kwala&lt;/strong&gt; lets you:&lt;br&gt;
✅ Define your backend logic declaratively&lt;br&gt;
✅ Automate smart contract actions effortlessly&lt;br&gt;
✅ Deploy without servers or infrastructure overhead&lt;/p&gt;

&lt;p&gt;During the Kwala Hacker House Hackathon, it helped my team build faster, smarter, and with less complexity — proving that &lt;strong&gt;automation is the next evolution of Web3 backend development&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Start building smarter today:&lt;/strong&gt; &lt;a href="https://kwala.network" rel="noopener noreferrer"&gt;https://kwala.network&lt;/a&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>kwala</category>
      <category>automation</category>
    </item>
    <item>
      <title>🧠 Day 30 of #30DaysOfSolidity — Build a Simple Token Exchange (AMM) Using Foundry</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Thu, 30 Oct 2025 18:31:02 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/day-30-of-30daysofsolidity-build-a-simple-token-exchange-amm-using-foundry-41nl</link>
      <guid>https://forem.com/sauravkumar8178/day-30-of-30daysofsolidity-build-a-simple-token-exchange-amm-using-foundry-41nl</guid>
      <description>&lt;p&gt;Building a &lt;strong&gt;decentralized exchange (DEX)&lt;/strong&gt; might sound complex, but today we’ll create a &lt;strong&gt;simple, constant-product Automated Market Maker (AMM)&lt;/strong&gt; from scratch using Solidity and Foundry — the foundation of DeFi platforms like Uniswap.&lt;/p&gt;

&lt;p&gt;This marks the final day of &lt;strong&gt;&lt;a href="https://www.web3compass.xyz/challenge-calendar" rel="noopener noreferrer"&gt;#30DaysOfSolidity&lt;/a&gt;&lt;/strong&gt;, and it’s the perfect way to wrap up the journey — by building your own mini DEX 🚀&lt;/p&gt;




&lt;h3&gt;
  
  
  💡 What You’ll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;How token swaps work without an order book&lt;/li&gt;
&lt;li&gt;How to create a liquidity pool and mint LP tokens&lt;/li&gt;
&lt;li&gt;How to calculate swap outputs using &lt;code&gt;x * y = k&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;How to apply trading fees and maintain balance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧱 Project Overview
&lt;/h2&gt;

&lt;p&gt;Our decentralized exchange allows users to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add liquidity&lt;/strong&gt; — deposit two tokens to form a trading pair.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swap tokens&lt;/strong&gt; — trade one token for another using the pool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove liquidity&lt;/strong&gt; — withdraw tokens by burning LP tokens.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll build three main contracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ExchangeFactory&lt;/code&gt; – creates and tracks trading pairs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ExchangePair&lt;/code&gt; – manages swaps, liquidity, and reserves.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MockERC20&lt;/code&gt; – simple mintable tokens for testing.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📂 Folder Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;day-30-solidity/
├─ src/
│  ├─ ERC20.sol
│  ├─ MockERC20.sol
│  ├─ ExchangeFactory.sol
│  └─ ExchangePair.sol
├─ script/
│  └─ Deploy.s.sol
├─ test/
│  └─ Exchange.t.sol
└─ README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 Step 1 — Minimal ERC20 Implementation (&lt;code&gt;ERC20.sol&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;We start with a lightweight ERC20 token for LP tokens used inside pairs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract ERC20 {
    string public name;
    string public symbol;
    uint8 public immutable decimals = 18;
    uint256 public totalSupply;

    mapping(address =&amp;gt; uint256) public balanceOf;
    mapping(address =&amp;gt; mapping(address =&amp;gt; uint256)) public allowance;

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    function _mint(address to, uint256 amount) internal {
        totalSupply += amount;
        balanceOf[to] += amount;
        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal {
        balanceOf[from] -= amount;
        totalSupply -= amount;
        emit Transfer(from, address(0), amount);
    }

    function approve(address spender, uint256 amount) external returns (bool) {
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    function transfer(address to, uint256 amount) external returns (bool) {
        _transfer(msg.sender, to, amount);
        return true;
    }

    function transferFrom(address from, address to, uint256 amount) external returns (bool) {
        uint256 allowed = allowance[from][msg.sender];
        if (allowed != type(uint256).max) {
            require(allowed &amp;gt;= amount, "ERC20: allowance");
            allowance[from][msg.sender] = allowed - amount;
        }
        _transfer(from, to, amount);
        return true;
    }

    function _transfer(address from, address to, uint256 amount) internal {
        require(balanceOf[from] &amp;gt;= amount, "ERC20: balance");
        balanceOf[from] -= amount;
        balanceOf[to] += amount;
        emit Transfer(from, to, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 Step 2 — Mock Tokens (&lt;code&gt;MockERC20.sol&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;We use mintable tokens for local testing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "./ERC20.sol";

contract MockERC20 is ERC20 {
    constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {}

    function mint(address to, uint256 amount) external {
        _mint(to, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 Step 3 — Exchange Pair Contract (&lt;code&gt;ExchangePair.sol&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;This is the heart of our AMM.&lt;br&gt;
It uses the constant product formula &lt;code&gt;x * y = k&lt;/code&gt; and 0.3% swap fee.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "./ERC20.sol";

interface IERC20Minimal {
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
    function transfer(address to, uint256 amount) external returns (bool);
    function balanceOf(address owner) external view returns (uint256);
}

contract ExchangePair is ERC20 {
    IERC20Minimal public token0;
    IERC20Minimal public token1;

    uint112 private reserve0;
    uint112 private reserve1;

    event Mint(address indexed sender, uint256 amount0, uint256 amount1, uint256 liquidity);
    event Burn(address indexed sender, address indexed to, uint256 amount0, uint256 amount1, uint256 liquidity);
    event Swap(address indexed sender, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out, address indexed to);
    event Sync(uint112 reserve0, uint112 reserve1);

    uint256 public constant FEE_NUM = 3;    // 0.3%
    uint256 public constant FEE_DEN = 1000;

    constructor(address _token0, address _token1) ERC20("Simple LP", "sLP") {
        require(_token0 != _token1, "IDENTICAL");
        token0 = IERC20Minimal(_token0);
        token1 = IERC20Minimal(_token1);
    }

    function getReserves() public view returns (uint112, uint112) {
        return (reserve0, reserve1);
    }

    function mint(address to) external returns (uint256 liquidity) {
        uint256 balance0 = token0.balanceOf(address(this));
        uint256 balance1 = token1.balanceOf(address(this));
        uint256 amount0 = balance0 - reserve0;
        uint256 amount1 = balance1 - reserve1;

        if (totalSupply == 0) {
            liquidity = _sqrt(amount0 * amount1);
        } else {
            liquidity = min((amount0 * totalSupply) / reserve0, (amount1 * totalSupply) / reserve1);
        }
        require(liquidity &amp;gt; 0, "INSUFFICIENT_LIQUIDITY");
        _mint(to, liquidity);

        _update(balance0, balance1);
        emit Mint(msg.sender, amount0, amount1, liquidity);
    }

    function burn(address to) external returns (uint256 amount0, uint256 amount1) {
        uint256 _totalSupply = totalSupply;
        uint256 liquidity = balanceOf[msg.sender];
        _burn(msg.sender, liquidity);

        amount0 = (liquidity * token0.balanceOf(address(this))) / _totalSupply;
        amount1 = (liquidity * token1.balanceOf(address(this))) / _totalSupply;

        require(amount0 &amp;gt; 0 &amp;amp;&amp;amp; amount1 &amp;gt; 0, "INSUFFICIENT_BURN");

        token0.transfer(to, amount0);
        token1.transfer(to, amount1);

        _update(token0.balanceOf(address(this)), token1.balanceOf(address(this)));
        emit Burn(msg.sender, to, amount0, amount1, liquidity);
    }

    function swap(uint256 amount0Out, uint256 amount1Out, address to) external {
        require(amount0Out &amp;gt; 0 || amount1Out &amp;gt; 0, "NO_OUTPUT");
        (uint112 _reserve0, uint112 _reserve1) = getReserves();

        if (amount0Out &amp;gt; 0) token0.transfer(to, amount0Out);
        if (amount1Out &amp;gt; 0) token1.transfer(to, amount1Out);

        uint256 balance0 = token0.balanceOf(address(this));
        uint256 balance1 = token1.balanceOf(address(this));

        uint256 amount0In = balance0 &amp;gt; _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
        uint256 amount1In = balance1 &amp;gt; _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
        require(amount0In &amp;gt; 0 || amount1In &amp;gt; 0, "NO_INPUT");

        uint256 balance0Adj = (balance0 * FEE_DEN) - (amount0In * FEE_NUM);
        uint256 balance1Adj = (balance1 * FEE_DEN) - (amount1In * FEE_NUM);
        require(balance0Adj * balance1Adj &amp;gt;= uint256(_reserve0) * uint256(_reserve1) * (FEE_DEN**2), "K");

        _update(balance0, balance1);
        emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
    }

    function _update(uint256 b0, uint256 b1) private {
        reserve0 = uint112(b0);
        reserve1 = uint112(b1);
        emit Sync(reserve0, reserve1);
    }

    function _sqrt(uint256 y) internal pure returns (uint256 z) {
        if (y == 0) return 0;
        uint256 x = y / 2 + 1;
        z = y;
        while (x &amp;lt; z) { z = x; x = (y / x + x) / 2; }
    }

    function min(uint256 a, uint256 b) private pure returns (uint256) {
        return a &amp;lt; b ? a : b;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 Step 4 — Factory Contract (&lt;code&gt;ExchangeFactory.sol&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;Manages creation and registry of pairs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "./ExchangePair.sol";

contract ExchangeFactory {
    mapping(address =&amp;gt; mapping(address =&amp;gt; address)) public getPair;
    address[] public allPairs;

    event PairCreated(address indexed token0, address indexed token1, address pair, uint256);

    function createPair(address tokenA, address tokenB) external returns (address pair) {
        require(tokenA != tokenB, "IDENTICAL_ADDRESSES");
        (address token0, address token1) = tokenA &amp;lt; tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(getPair[token0][token1] == address(0), "PAIR_EXISTS");

        ExchangePair newPair = new ExchangePair(token0, token1);
        pair = address(newPair);
        getPair[token0][token1] = pair;
        getPair[token1][token0] = pair;
        allPairs.push(pair);

        emit PairCreated(token0, token1, pair, allPairs.length);
    }

    function allPairsLength() external view returns (uint256) {
        return allPairs.length;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Step 5 — Testing the Exchange (&lt;code&gt;Exchange.t.sol&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;A quick Foundry test verifying liquidity and swaps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "forge-std/Test.sol";
import "../src/ExchangeFactory.sol";
import "../src/MockERC20.sol";
import "../src/ExchangePair.sol";

contract ExchangeTest is Test {
    ExchangeFactory factory;
    MockERC20 tokenA;
    MockERC20 tokenB;
    ExchangePair pair;

    function setUp() public {
        factory = new ExchangeFactory();
        tokenA = new MockERC20("Token A", "TKA");
        tokenB = new MockERC20("Token B", "TKB");
        address pairAddr = factory.createPair(address(tokenA), address(tokenB));
        pair = ExchangePair(pairAddr);

        tokenA.mint(address(this), 1_000_000 ether);
        tokenB.mint(address(this), 1_000_000 ether);
    }

    function testLiquidityAndSwap() public {
        tokenA.transfer(address(pair), 1000 ether);
        tokenB.transfer(address(pair), 1000 ether);
        pair.mint(address(this));

        tokenA.transfer(address(pair), 10 ether);
        pair.swap(0, 9 ether, address(this));

        (uint112 r0, uint112 r1) = pair.getReserves();
        assertTrue(r0 &amp;gt; 0 &amp;amp;&amp;amp; r1 &amp;gt; 0);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚙️ Run Locally
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Install Foundry&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://foundry.paradigm.xyz | bash
   foundryup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Clone project&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   git clone &amp;lt;your_repo_url&amp;gt;
   &lt;span class="nb"&gt;cd &lt;/span&gt;day-30-solidity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run tests&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deploy&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   forge script script/Deploy.s.sol:DeployScript &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; &amp;lt;RPC_URL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 How the AMM Maintains Balance
&lt;/h2&gt;

&lt;p&gt;Every swap obeys:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x * y = k
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; are the reserves of both tokens.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;k&lt;/code&gt; is a constant that should never decrease.
By adjusting &lt;code&gt;x&lt;/code&gt; or &lt;code&gt;y&lt;/code&gt;, the price automatically rebalances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The swap fee slightly increases reserves over time, rewarding liquidity providers.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 What You’ve Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built a mini-Uniswap from scratch&lt;/li&gt;
&lt;li&gt;Understood the constant-product formula&lt;/li&gt;
&lt;li&gt;Implemented token swaps, mint/burn LP tokens&lt;/li&gt;
&lt;li&gt;Used Foundry for professional-grade Solidity testing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This completes &lt;strong&gt;Day 30 of #30DaysOfSolidity&lt;/strong&gt; 🎉&lt;br&gt;
You’ve now built:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A stablecoin&lt;/li&gt;
&lt;li&gt;Lending/Borrowing systems&lt;/li&gt;
&lt;li&gt;DAOs, Escrow, NFT Marketplaces&lt;/li&gt;
&lt;li&gt;and finally — a Decentralized Exchange.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each day has taken you a step closer to &lt;strong&gt;real-world DeFi mastery&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you found this helpful, drop a ❤️ on &lt;a href="https://dev.to/"&gt;Dev.to&lt;/a&gt; and share your version!&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>web3</category>
      <category>tutorial</category>
      <category>challenge</category>
    </item>
    <item>
      <title>🪙 Day 29 of #30DaysOfSolidity — Building a Collateral-Backed Stablecoin in Solidity — Step-by-Step Guide</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Wed, 29 Oct 2025 21:11:09 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/day-29-of-30daysofsolidity-building-a-collateral-backed-stablecoin-in-solidity-step-by-step-6dd</link>
      <guid>https://forem.com/sauravkumar8178/day-29-of-30daysofsolidity-building-a-collateral-backed-stablecoin-in-solidity-step-by-step-6dd</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Saurav Kumar&lt;br&gt;
&lt;strong&gt;Tags:&lt;/strong&gt; &lt;code&gt;solidity&lt;/code&gt;, &lt;code&gt;defi&lt;/code&gt;, &lt;code&gt;stablecoin&lt;/code&gt;, &lt;code&gt;ethereum&lt;/code&gt;, &lt;code&gt;blockchain&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate → Advanced&lt;br&gt;
&lt;strong&gt;Reading Time:&lt;/strong&gt; ~10 minutes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  💡 Introduction
&lt;/h2&gt;

&lt;p&gt;In decentralized finance (DeFi), &lt;strong&gt;stablecoins&lt;/strong&gt; play a crucial role in bridging traditional finance and crypto.&lt;br&gt;
They provide &lt;strong&gt;price stability&lt;/strong&gt;, &lt;strong&gt;liquidity&lt;/strong&gt;, and &lt;strong&gt;on-chain utility&lt;/strong&gt;—acting as the backbone of protocols like &lt;strong&gt;MakerDAO (DAI)&lt;/strong&gt;, &lt;strong&gt;Aave&lt;/strong&gt;, and &lt;strong&gt;Curve&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll build a &lt;strong&gt;collateral-backed stablecoin&lt;/strong&gt; named &lt;code&gt;StableUSD (sUSD)&lt;/code&gt; using &lt;strong&gt;Solidity&lt;/strong&gt; and &lt;strong&gt;Foundry&lt;/strong&gt;, demonstrating how to maintain a 1:1 peg to the US dollar through &lt;strong&gt;collateralization&lt;/strong&gt; and &lt;strong&gt;oracle-based pricing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This article is part of my &lt;strong&gt;DeFi Engineering Series&lt;/strong&gt;, where I recreate real-world protocols from scratch.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 What You’ll Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How stablecoins maintain their price peg&lt;/li&gt;
&lt;li&gt;How to design collateralized minting and redemption flows&lt;/li&gt;
&lt;li&gt;How to integrate oracles (mock or Chainlink-style)&lt;/li&gt;
&lt;li&gt;How to implement collateralization ratios and burn/mint mechanics&lt;/li&gt;
&lt;li&gt;How to test everything using &lt;strong&gt;Foundry&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  📂 Project File Structure
&lt;/h2&gt;

&lt;p&gt;Here’s the Foundry project layout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;day-29-stablecoin/
├─ foundry.toml
├─ .gitignore
├─ script/
│   └─ Deploy.s.sol
├─ src/
│   ├─ StableUSD.sol
│   ├─ OracleManager.sol
│   ├─ CollateralPool.sol
│   ├─ Treasury.sol
│   ├─ MockOracle.sol
│   ├─ MockERC20.sol
│   └─ interfaces/
│       └─ IAggregatorV3.sol
└─ test/
    └─ Stablecoin.t.sol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 System Overview
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;StableUSD.sol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ERC20 token for sUSD, mint/burn controlled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OracleManager.sol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Connects to Chainlink or mock price feeds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CollateralPool.sol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Core logic for deposits, minting &amp;amp; redemption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Treasury.sol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Admin contract for reserves and fee collection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🏗️ Architecture Diagram
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User → CollateralPool → StableUSD  
           ↓  
        OracleManager  
           ↓  
         Treasury
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Users&lt;/strong&gt; deposit collateral (e.g., WETH).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OracleManager&lt;/strong&gt; provides price data in USD.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CollateralPool&lt;/strong&gt; mints &lt;code&gt;sUSD&lt;/code&gt; tokens based on collateral value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treasury&lt;/strong&gt; manages reserves and stability actions.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚙️ Setup Commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge init day-29-stablecoin
&lt;span class="nb"&gt;cd &lt;/span&gt;day-29-stablecoin
forge &lt;span class="nb"&gt;install &lt;/span&gt;OpenZeppelin/openzeppelin-contracts
forge &lt;span class="nb"&gt;install &lt;/span&gt;foundry-rs/forge-std
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 Smart Contracts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📁 &lt;code&gt;src/interfaces/IAggregatorV3.sol&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IAggregatorV3 {
    function latestRoundData()
        external
        view
        returns (
            uint80,
            int256 answer,
            uint256,
            uint256,
            uint80
        );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  📁 &lt;code&gt;src/StableUSD.sol&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";

contract StableUSD is ERC20, AccessControl {
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

    constructor() ERC20("Stable USD", "sUSD") {
        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }

    function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
        _mint(to, amount);
    }

    function burn(address from, uint256 amount) external onlyRole(MINTER_ROLE) {
        _burn(from, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Implements ERC20&lt;br&gt;
✅ Controlled mint/burn via roles&lt;/p&gt;


&lt;h3&gt;
  
  
  📁 &lt;code&gt;src/OracleManager.sol&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "./interfaces/IAggregatorV3.sol";

contract OracleManager {
    IAggregatorV3 public oracle;

    constructor(address _oracle) {
        oracle = IAggregatorV3(_oracle);
    }

    function getLatestPrice() external view returns (uint256) {
        (, int256 answer,,,) = oracle.latestRoundData();
        require(answer &amp;gt; 0, "Invalid price");
        return uint256(answer);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;💡 Use Chainlink price feeds for live ETH/USD in production.&lt;/p&gt;


&lt;h3&gt;
  
  
  📁 &lt;code&gt;src/MockOracle.sol&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract MockOracle {
    int256 private price;

    constructor(int256 _price) {
        price = _price;
    }

    function latestRoundData()
        external
        view
        returns (uint80, int256, uint256, uint256, uint80)
    {
        return (0, price, 0, 0, 0);
    }

    function updatePrice(int256 _price) external {
        price = _price;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;✅ Simulates Chainlink oracles for local testing&lt;/p&gt;


&lt;h3&gt;
  
  
  📁 &lt;code&gt;src/MockERC20.sol&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MockERC20 is ERC20 {
    constructor(string memory name, string memory symbol) ERC20(name, symbol) {}

    function mint(address to, uint256 amount) external {
        _mint(to, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;✅ Mock collateral asset (like WETH) for testing mint/redeem logic&lt;/p&gt;


&lt;h3&gt;
  
  
  📁 &lt;code&gt;src/CollateralPool.sol&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./StableUSD.sol";
import "./OracleManager.sol";

contract CollateralPool {
    IERC20 public collateral;
    StableUSD public stable;
    OracleManager public oracle;

    uint256 public constant COLLATERAL_RATIO = 150; // 150%
    mapping(address =&amp;gt; uint256) public collateralBalance;

    constructor(IERC20 _collateral, StableUSD _stable, OracleManager _oracle) {
        collateral = _collateral;
        stable = _stable;
        oracle = _oracle;
    }

    function deposit(uint256 amount) external {
        require(amount &amp;gt; 0, "Invalid amount");
        collateral.transferFrom(msg.sender, address(this), amount);
        collateralBalance[msg.sender] += amount;
    }

    function mint(uint256 amountCollateral) external {
        require(collateralBalance[msg.sender] &amp;gt;= amountCollateral, "Insufficient collateral");

        uint256 price = oracle.getLatestPrice();
        uint256 usdValue = (amountCollateral * price) / 1e8;
        uint256 mintAmount = (usdValue * 100) / COLLATERAL_RATIO;

        stable.mint(msg.sender, mintAmount * 1e18);
    }

    function redeem(uint256 sUSDAmount) external {
        stable.burn(msg.sender, sUSDAmount);

        uint256 price = oracle.getLatestPrice();
        uint256 collateralToReturn = (sUSDAmount * 1e8 * COLLATERAL_RATIO) / (price * 100);

        require(collateralBalance[msg.sender] &amp;gt;= collateralToReturn, "Not enough collateral");
        collateralBalance[msg.sender] -= collateralToReturn;
        collateral.transfer(msg.sender, collateralToReturn);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;⚡ Implements over-collateralized mint/redeem flow&lt;br&gt;
⚡ Maintains peg using oracle price&lt;br&gt;
⚡ 150% ratio ensures safety&lt;/p&gt;


&lt;h3&gt;
  
  
  📁 &lt;code&gt;src/Treasury.sol&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Treasury {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    function withdraw(address token, address to, uint256 amount) external {
        require(msg.sender == owner, "Not authorized");
        (bool ok,) = token.call(abi.encodeWithSignature("transfer(address,uint256)", to, amount));
        require(ok, "Transfer failed");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;✅ Simple treasury for system fund management&lt;/p&gt;


&lt;h3&gt;
  
  
  📁 &lt;code&gt;script/Deploy.s.sol&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Script.sol";
import "../src/StableUSD.sol";
import "../src/OracleManager.sol";
import "../src/CollateralPool.sol";
import "../src/MockERC20.sol";
import "../src/MockOracle.sol";

contract Deploy is Script {
    function run() external {
        vm.startBroadcast();

        MockERC20 collateral = new MockERC20("Wrapped ETH", "WETH");
        MockOracle oracle = new MockOracle(1800e8);
        StableUSD stable = new StableUSD();
        OracleManager oracleManager = new OracleManager(address(oracle));
        CollateralPool pool = new CollateralPool(collateral, stable, oracleManager);

        stable.grantRole(stable.MINTER_ROLE(), address(pool));

        vm.stopBroadcast();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;✅ Deploys all components in one transaction&lt;/p&gt;


&lt;h3&gt;
  
  
  📁 &lt;code&gt;test/Stablecoin.t.sol&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "../src/StableUSD.sol";
import "../src/CollateralPool.sol";
import "../src/OracleManager.sol";
import "../src/MockERC20.sol";
import "../src/MockOracle.sol";

contract StablecoinTest is Test {
    StableUSD stable;
    OracleManager oracle;
    CollateralPool pool;
    MockERC20 collateral;

    function setUp() public {
        collateral = new MockERC20("Wrapped ETH", "WETH");
        stable = new StableUSD();
        oracle = new OracleManager(address(new MockOracle(1800e8)));
        pool = new CollateralPool(IERC20(address(collateral)), stable, oracle);
        stable.grantRole(stable.MINTER_ROLE(), address(pool));
    }

    function testMintStablecoin() public {
        collateral.mint(address(this), 1 ether);
        collateral.approve(address(pool), 1 ether);
        pool.deposit(1 ether);
        pool.mint(1 ether);
        assertGt(stable.balanceOf(address(this)), 0);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;✅ Tests deposit → mint flow&lt;br&gt;
✅ Confirms minting works using oracle-based pricing&lt;/p&gt;


&lt;h2&gt;
  
  
  🧪 Test &amp;amp; Run
&lt;/h2&gt;


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

&lt;/div&gt;



&lt;h2&gt;
  
  
  🧮 Peg Example
&lt;/h2&gt;

&lt;p&gt;If &lt;strong&gt;1 ETH = $1800&lt;/strong&gt; and collateral ratio = &lt;strong&gt;150%&lt;/strong&gt;,&lt;br&gt;
then 1 ETH mints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(1800 * 100 / 150) = 1200 sUSD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧠 Key Learnings
&lt;/h2&gt;

&lt;p&gt;✅ How stablecoins maintain a peg&lt;br&gt;
✅ Using oracles to stabilize token value&lt;br&gt;
✅ Over-collateralization mechanics&lt;br&gt;
✅ Writing and testing DeFi smart contracts&lt;/p&gt;




&lt;h2&gt;
  
  
  🛡️ Security &amp;amp; Design Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always use &lt;strong&gt;verified Chainlink oracles&lt;/strong&gt; in production.&lt;/li&gt;
&lt;li&gt;Implement &lt;strong&gt;liquidation logic&lt;/strong&gt; for under-collateralized users.&lt;/li&gt;
&lt;li&gt;Add &lt;strong&gt;pause and governance controls&lt;/strong&gt; for protocol safety.&lt;/li&gt;
&lt;li&gt;Track &lt;strong&gt;debt positions per user&lt;/strong&gt; in a full system.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multi-collateral vaults (ETH, USDC, WBTC)&lt;/li&gt;
&lt;li&gt;Dynamic interest and stability fees&lt;/li&gt;
&lt;li&gt;DAO-based parameter governance&lt;/li&gt;
&lt;li&gt;Integration with Uniswap for peg stabilization&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Stablecoins are the &lt;strong&gt;core monetary layer of DeFi&lt;/strong&gt; — building one from scratch deepens your understanding of price oracles, collateralization, and supply control.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;StableUSD&lt;/code&gt; demo shows how &lt;strong&gt;trustless monetary systems&lt;/strong&gt; can maintain stability purely through code and math.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🗳️ Day 28 of #30DaysOfSolidity — Build a DAO Voting System (Decentralized Governance)</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Wed, 29 Oct 2025 20:38:23 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/day-28-of-30daysofsolidity-build-a-dao-voting-system-decentralized-governance-3kg1</link>
      <guid>https://forem.com/sauravkumar8178/day-28-of-30daysofsolidity-build-a-dao-voting-system-decentralized-governance-3kg1</guid>
      <description>&lt;p&gt;In today’s challenge, we’ll build a &lt;strong&gt;DAO Voting System&lt;/strong&gt; — the backbone of &lt;strong&gt;Decentralized Governance&lt;/strong&gt;.&lt;br&gt;
It’s like a &lt;strong&gt;digital democracy&lt;/strong&gt; where members can &lt;strong&gt;propose&lt;/strong&gt;, &lt;strong&gt;vote&lt;/strong&gt;, and &lt;strong&gt;execute decisions&lt;/strong&gt; — all powered by &lt;strong&gt;smart contracts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s dive into how DAOs (Decentralized Autonomous Organizations) function on-chain and build our own using &lt;strong&gt;Solidity + Foundry&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  💡 What is a DAO?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;DAO (Decentralized Autonomous Organization)&lt;/strong&gt; is a community-led entity with no central authority.&lt;br&gt;
Every decision — like protocol upgrades or treasury spending — is made through &lt;strong&gt;proposals and votes&lt;/strong&gt; recorded on-chain.&lt;/p&gt;

&lt;p&gt;Our DAO will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Allow &lt;strong&gt;members&lt;/strong&gt; to create proposals.&lt;/li&gt;
&lt;li&gt;Let members &lt;strong&gt;vote for or against&lt;/strong&gt; proposals.&lt;/li&gt;
&lt;li&gt;Automatically &lt;strong&gt;execute&lt;/strong&gt; successful proposals.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🧱 Project Structure
&lt;/h2&gt;

&lt;p&gt;Here’s the layout for our DAO project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;day-28-solidity/
├─ src/
│  └─ SimpleDAO.sol
├─ test/
│  └─ SimpleDAO.t.sol
├─ script/
│  └─ deploy.s.sol
├─ foundry.toml
└─ README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚙️ Smart Contract — &lt;code&gt;SimpleDAO.sol&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Below is the full Solidity code implementing our DAO logic 👇&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/// @title SimpleDAO - member-based governance for proposals &amp;amp; voting
/// @notice Demonstrates decentralized decision-making and on-chain governance.
contract SimpleDAO {
    event MemberAdded(address indexed member);
    event MemberRemoved(address indexed member);
    event ProposalCreated(uint256 indexed id, address indexed proposer, uint256 startTime, uint256 endTime, string description);
    event VoteCast(address indexed voter, uint256 indexed proposalId, bool support);
    event ProposalExecuted(uint256 indexed id);

    struct Proposal {
        uint256 id;
        address proposer;
        address[] targets;
        uint256[] values;
        bytes[] calldatas;
        string description;
        uint256 startTime;
        uint256 endTime;
        uint256 forVotes;
        uint256 againstVotes;
        bool executed;
        bool canceled;
    }

    mapping(address =&amp;gt; bool) public isMember;
    uint256 public memberCount;

    mapping(uint256 =&amp;gt; Proposal) public proposals;
    uint256 public proposalCount;
    mapping(uint256 =&amp;gt; mapping(address =&amp;gt; bool)) public hasVoted;

    uint256 public votingPeriod;
    uint256 public quorum;
    address public admin;

    modifier onlyAdmin() {
        require(msg.sender == admin, "Only admin");
        _;
    }

    modifier onlyMember() {
        require(isMember[msg.sender], "Not a member");
        _;
    }

    constructor(uint256 _votingPeriodSeconds, uint256 _quorum) {
        votingPeriod = _votingPeriodSeconds;
        quorum = _quorum;
        admin = msg.sender;
    }

    function addMember(address _member) external onlyAdmin {
        require(!isMember[_member], "Already member");
        isMember[_member] = true;
        memberCount++;
        emit MemberAdded(_member);
    }

    function removeMember(address _member) external onlyAdmin {
        require(isMember[_member], "Not member");
        isMember[_member] = false;
        memberCount--;
        emit MemberRemoved(_member);
    }

    function propose(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata calldatas,
        string calldata description
    ) external onlyMember returns (uint256) {
        require(targets.length &amp;gt; 0, "Empty proposal");

        proposalCount++;
        uint256 id = proposalCount;

        proposals[id] = Proposal({
            id: id,
            proposer: msg.sender,
            targets: targets,
            values: values,
            calldatas: calldatas,
            description: description,
            startTime: block.timestamp,
            endTime: block.timestamp + votingPeriod,
            forVotes: 0,
            againstVotes: 0,
            executed: false,
            canceled: false
        });

        emit ProposalCreated(id, msg.sender, block.timestamp, block.timestamp + votingPeriod, description);
        return id;
    }

    function vote(uint256 proposalId, bool support) external onlyMember {
        Proposal storage p = proposals[proposalId];
        require(block.timestamp &amp;lt;= p.endTime, "Voting ended");
        require(!hasVoted[proposalId][msg.sender], "Already voted");

        hasVoted[proposalId][msg.sender] = true;
        if (support) p.forVotes++;
        else p.againstVotes++;

        emit VoteCast(msg.sender, proposalId, support);
    }

    function execute(uint256 proposalId) external {
        Proposal storage p = proposals[proposalId];
        require(block.timestamp &amp;gt; p.endTime, "Voting not ended");
        require(!p.executed, "Already executed");
        require(p.forVotes &amp;gt;= quorum &amp;amp;&amp;amp; p.forVotes &amp;gt; p.againstVotes, "Proposal failed");

        p.executed = true;
        for (uint256 i = 0; i &amp;lt; p.targets.length; i++) {
            (bool success, ) = p.targets[i].call{value: p.values[i]}(p.calldatas[i]);
            require(success, "Execution failed");
        }

        emit ProposalExecuted(proposalId);
    }

    receive() external payable {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Testing the DAO (Foundry)
&lt;/h2&gt;

&lt;p&gt;Testing ensures our proposal → vote → execute flow works perfectly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "forge-std/Test.sol";
import "../src/SimpleDAO.sol";

contract DummyTarget {
    event Done(address sender);
    function doSomething() external {
        emit Done(msg.sender);
    }
}

contract SimpleDAOTest is Test {
    SimpleDAO dao;
    DummyTarget target;

    address alice = address(0xA11CE);
    address bob   = address(0xB0B);

    function setUp() public {
        dao = new SimpleDAO(1 hours, 2);
        dao.addMember(alice);
        dao.addMember(bob);
        target = new DummyTarget();
    }

    function testProposalLifecycle() public {
        vm.prank(alice);
        address ;
        targets[0] = address(target);
        uint256 ;
        values[0] = 0;
        bytes ;
        calldatas[0] = abi.encodeWithSelector(DummyTarget.doSomething.selector);

        vm.prank(alice);
        uint256 id = dao.propose(targets, values, calldatas, "Trigger doSomething()");

        vm.warp(block.timestamp + 10);
        vm.prank(alice);
        dao.vote(id, true);
        vm.prank(bob);
        dao.vote(id, true);

        vm.warp(block.timestamp + 1 hours + 1);
        dao.execute(id);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Run test:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧭 How It Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Admin adds members&lt;/strong&gt; who can vote.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Members create proposals&lt;/strong&gt; describing actions the DAO should take.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Voting starts&lt;/strong&gt; immediately after proposal creation.&lt;/li&gt;
&lt;li&gt;Members &lt;strong&gt;vote For or Against&lt;/strong&gt; the proposal.&lt;/li&gt;
&lt;li&gt;Once the voting period ends, if quorum is met and “for” votes win, &lt;strong&gt;the proposal executes automatically&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🧩 Example Scenario
&lt;/h2&gt;

&lt;p&gt;Imagine a &lt;strong&gt;community treasury DAO&lt;/strong&gt; with 10 members:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A proposal is created to donate 2 ETH to an education project.&lt;/li&gt;
&lt;li&gt;Members vote.&lt;/li&gt;
&lt;li&gt;If majority agrees and quorum is reached, funds are sent automatically!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛡️ Security Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Only members&lt;/strong&gt; can propose or vote.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quorum and majority&lt;/strong&gt; ensure fairness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution&lt;/strong&gt; is atomic — if any call fails, the entire transaction reverts.&lt;/li&gt;
&lt;li&gt;This version uses &lt;strong&gt;admin control for simplicity&lt;/strong&gt;, but production DAOs should use &lt;strong&gt;token-based voting&lt;/strong&gt; and &lt;strong&gt;timelocks&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚡ Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Deploy it locally using Foundry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge create src/SimpleDAO.sol:SimpleDAO &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; &amp;lt;RPC_URL&amp;gt; &lt;span class="nt"&gt;--private-key&lt;/span&gt; &amp;lt;PRIVATE_KEY&amp;gt; &lt;span class="nt"&gt;--constructor-args&lt;/span&gt; 3600 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use &lt;a href="https://book.getfoundry.sh/reference/cast/" rel="noopener noreferrer"&gt;Cast&lt;/a&gt; to call methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cast send &amp;lt;DAO_ADDRESS&amp;gt; &lt;span class="s2"&gt;"addMember(address)"&lt;/span&gt; &amp;lt;YOUR_MEMBER_ADDRESS&amp;gt; &lt;span class="nt"&gt;--private-key&lt;/span&gt; &amp;lt;PRIVATE_KEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Future Enhancements
&lt;/h2&gt;

&lt;p&gt;You can level up this DAO with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🪙 ERC20-based token voting (snapshot)&lt;/li&gt;
&lt;li&gt;⏱️ Timelocks for proposal execution delay&lt;/li&gt;
&lt;li&gt;🧾 Proposal cancellation / expiry&lt;/li&gt;
&lt;li&gt;🗳️ Off-chain voting via signatures (gasless)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Summary
&lt;/h2&gt;

&lt;p&gt;In this project, you learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create and manage proposals&lt;/li&gt;
&lt;li&gt;Implement on-chain voting logic&lt;/li&gt;
&lt;li&gt;Execute decentralized governance decisions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This forms the &lt;strong&gt;core foundation of DAOs&lt;/strong&gt; — transparent, autonomous, and democratic organizations on blockchain.&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;DAOs are the future of &lt;strong&gt;collective decision-making&lt;/strong&gt;.&lt;br&gt;
By mastering these core governance concepts, you can build your own decentralized organizations that run purely by community consensus.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>ethereum</category>
      <category>web3</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🪙 Day 27 of #30DaysOfSolidity — Build a Staking &amp; Yield Farming Platform in Solidity</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Wed, 29 Oct 2025 20:30:56 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/day-27-of-30daysofsolidity-build-a-staking-yield-farming-platform-in-solidity-49k3</link>
      <guid>https://forem.com/sauravkumar8178/day-27-of-30daysofsolidity-build-a-staking-yield-farming-platform-in-solidity-49k3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Turn your tokens into a source of passive income 💰&lt;br&gt;
Learn how staking and yield farming work by building your own reward distribution system on Ethereum!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧭 Overview
&lt;/h2&gt;

&lt;p&gt;In this project, we’ll build a &lt;strong&gt;Staking Rewards System&lt;/strong&gt; — where users deposit tokens and earn periodic rewards in another token.&lt;/p&gt;

&lt;p&gt;It’s just like a &lt;strong&gt;digital savings account&lt;/strong&gt; that pays &lt;strong&gt;interest in tokens&lt;/strong&gt; — demonstrating one of the core mechanisms in &lt;strong&gt;DeFi (Decentralized Finance)&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;day-27-staking-rewards/
├─ foundry.toml
├─ src/
│  ├─ MockERC20.sol
│  └─ StakingRewards.sol
├─ script/
│  └─ Deploy.s.sol
└─ test/
   └─ StakingRewards.t.sol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ll use &lt;strong&gt;Foundry&lt;/strong&gt; for smart contract testing and deployment — it’s fast, lightweight, and ideal for local blockchain development.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚙️ Step 1 — Setup
&lt;/h2&gt;

&lt;p&gt;Install Foundry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://foundry.paradigm.xyz | bash
foundryup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Initialize the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge init day-27-staking-rewards
&lt;span class="nb"&gt;cd &lt;/span&gt;day-27-staking-rewards
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💰 Step 2 — Create a Mock Token
&lt;/h2&gt;

&lt;p&gt;We’ll create a mock ERC20 token for both staking and rewards.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MockERC20 is ERC20 {
    constructor(string memory name, string memory symbol, uint256 initialSupply)
        ERC20(name, symbol)
    {
        _mint(msg.sender, initialSupply);
    }

    function mint(address to, uint256 amount) external {
        _mint(to, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏦 Step 3 — Build the StakingRewards Contract
&lt;/h2&gt;

&lt;p&gt;Here’s the core of our yield farming system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract StakingRewards is Ownable, ReentrancyGuard {
    using SafeERC20 for IERC20;

    IERC20 public immutable stakeToken;
    IERC20 public immutable rewardToken;

    uint256 public totalSupply;
    mapping(address =&amp;gt; uint256) public balances;

    uint256 public rewardPerTokenStored;
    uint256 public lastUpdateTime;
    uint256 public rewardRate;
    uint256 private constant PRECISION = 1e18;

    mapping(address =&amp;gt; uint256) public userRewardPerTokenPaid;
    mapping(address =&amp;gt; uint256) public rewards;

    event Staked(address indexed user, uint256 amount);
    event Withdrawn(address indexed user, uint256 amount);
    event RewardPaid(address indexed user, uint256 reward);
    event RewardRateUpdated(uint256 oldRate, uint256 newRate);

    constructor(address _stakeToken, address _rewardToken) {
        stakeToken = IERC20(_stakeToken);
        rewardToken = IERC20(_rewardToken);
        lastUpdateTime = block.timestamp;
    }

    modifier updateReward(address account) {
        _updateRewardPerToken();
        if (account != address(0)) {
            rewards[account] = earned(account);
            userRewardPerTokenPaid[account] = rewardPerTokenStored;
        }
        _;
    }

    function _updateRewardPerToken() internal {
        if (totalSupply == 0) {
            lastUpdateTime = block.timestamp;
            return;
        }
        uint256 time = block.timestamp - lastUpdateTime;
        uint256 rewardAccrued = time * rewardRate;
        rewardPerTokenStored += (rewardAccrued * PRECISION) / totalSupply;
        lastUpdateTime = block.timestamp;
    }

    function notifyRewardAmount(uint256 reward, uint256 duration)
        external
        onlyOwner
        updateReward(address(0))
    {
        require(duration &amp;gt; 0, "duration&amp;gt;0");
        rewardToken.safeTransferFrom(msg.sender, address(this), reward);
        uint256 newRate = reward / duration;
        emit RewardRateUpdated(rewardRate, newRate);
        rewardRate = newRate;
    }

    function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
        require(amount &amp;gt; 0, "amount&amp;gt;0");
        totalSupply += amount;
        balances[msg.sender] += amount;
        stakeToken.safeTransferFrom(msg.sender, address(this), amount);
        emit Staked(msg.sender, amount);
    }

    function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
        require(amount &amp;gt; 0, "amount&amp;gt;0");
        totalSupply -= amount;
        balances[msg.sender] -= amount;
        stakeToken.safeTransfer(msg.sender, amount);
        emit Withdrawn(msg.sender, amount);
    }

    function getReward() public nonReentrant updateReward(msg.sender) {
        uint256 reward = rewards[msg.sender];
        if (reward &amp;gt; 0) {
            rewards[msg.sender] = 0;
            rewardToken.safeTransfer(msg.sender, reward);
            emit RewardPaid(msg.sender, reward);
        }
    }

    function exit() external {
        withdraw(balances[msg.sender]);
        getReward();
    }

    function earned(address account) public view returns (uint256) {
        uint256 _balance = balances[account];
        uint256 _rewardPerToken = rewardPerTokenStored;
        if (totalSupply != 0) {
            uint256 time = block.timestamp - lastUpdateTime;
            uint256 pending = time * rewardRate;
            _rewardPerToken += (pending * PRECISION) / totalSupply;
        }
        return (_balance * (_rewardPerToken - userRewardPerTokenPaid[account])) / PRECISION + rewards[account];
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Step 4 — Write Tests (Foundry)
&lt;/h2&gt;

&lt;p&gt;Here’s a simple test case to verify our staking logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "forge-std/Test.sol";
import "../src/MockERC20.sol";
import "../src/StakingRewards.sol";

contract StakingRewardsTest is Test {
    MockERC20 stake;
    MockERC20 reward;
    StakingRewards staking;
    address alice = address(0xA11CE);

    function setUp() public {
        stake = new MockERC20("Stake Token", "STK", 0);
        reward = new MockERC20("Reward Token", "RWD", 0);
        staking = new StakingRewards(address(stake), address(reward));

        stake.mint(alice, 1000 ether);
        reward.mint(address(this), 1000 ether);
        reward.approve(address(staking), type(uint256).max);
    }

    function testStakeAndEarn() public {
        staking.notifyRewardAmount(100 ether, 100);
        vm.prank(alice);
        stake.approve(address(staking), 100 ether);
        vm.prank(alice);
        staking.stake(100 ether);
        vm.warp(block.timestamp + 50);
        uint256 earned = staking.earned(alice);
        assertApproxEqRel(earned, 50 ether, 1e16);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run tests:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  💡 Step 5 — Deploy Script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "forge-std/Script.sol";
import "../src/MockERC20.sol";
import "../src/StakingRewards.sol";

contract DeployScript is Script {
    function run() public {
        vm.startBroadcast();
        MockERC20 stake = new MockERC20("Stake Token", "STK", 1_000_000 ether);
        MockERC20 reward = new MockERC20("Reward Token", "RWD", 1_000_000 ether);
        StakingRewards staking = new StakingRewards(address(stake), address(reward));
        vm.stopBroadcast();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔐 Security Tips
&lt;/h2&gt;

&lt;p&gt;✅ Use &lt;code&gt;nonReentrant&lt;/code&gt; modifier&lt;br&gt;
✅ Validate inputs before transfers&lt;br&gt;
✅ Keep reward logic owner-only&lt;br&gt;
✅ Test for edge cases like 0 stake or high reward rates&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What You Built
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A complete &lt;strong&gt;staking &amp;amp; yield farming platform&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Users can &lt;strong&gt;stake, earn rewards, and withdraw anytime&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Reward distribution is &lt;strong&gt;fair and time-based&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Built with &lt;strong&gt;Foundry&lt;/strong&gt;, &lt;strong&gt;OpenZeppelin&lt;/strong&gt;, and &lt;strong&gt;best Solidity practices&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Next Challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add multiple staking pools&lt;/li&gt;
&lt;li&gt;Introduce NFT-based reward boosts&lt;/li&gt;
&lt;li&gt;Build a React or Next.js frontend using Ethers.js&lt;/li&gt;
&lt;li&gt;Automate reward top-ups with Chainlink Keepers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 GitHub Repository
&lt;/h2&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/sauravkumar8178/30-days-of-solidity-submissions/tree/main/submissions/sauravkumar8178/day-27-solidity" rel="noopener noreferrer"&gt;GitHub: Day 27 — Staking &amp;amp; Yield Farming (Solidity)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>tutorial</category>
      <category>web3</category>
    </item>
    <item>
      <title>🏪 Day 26 of #30DaysOfSolidity — Build a Decentralized NFT Marketplace with Royalties 💎</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Wed, 29 Oct 2025 20:24:19 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/day-26-of-30daysofsolidity-build-a-decentralized-nft-marketplace-with-royalties-2nk7</link>
      <guid>https://forem.com/sauravkumar8178/day-26-of-30daysofsolidity-build-a-decentralized-nft-marketplace-with-royalties-2nk7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Today, we’re building a &lt;strong&gt;fully functional NFT Marketplace&lt;/strong&gt; in Solidity — a platform where users can &lt;strong&gt;buy, sell, and trade NFTs&lt;/strong&gt;, while automatically paying &lt;strong&gt;royalties to creators&lt;/strong&gt; and &lt;strong&gt;fees to the platform&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It’s like creating your own &lt;strong&gt;digital store for NFTs&lt;/strong&gt;, powered entirely by smart contracts! ⚡&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧠 What You’ll Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How NFT marketplaces work on-chain&lt;/li&gt;
&lt;li&gt;Listing and buying NFTs with ETH&lt;/li&gt;
&lt;li&gt;Applying ERC-2981 royalties for creators&lt;/li&gt;
&lt;li&gt;Adding marketplace fees&lt;/li&gt;
&lt;li&gt;Preventing reentrancy &amp;amp; ensuring safe transfers&lt;/li&gt;
&lt;li&gt;Testing &amp;amp; deploying with Foundry&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧱 Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;day-26-nft-marketplace/
├─ foundry.toml
├─ src/
│  ├─ NFTCollection.sol
│  └─ NFTMarketplace.sol
├─ test/
│  └─ Marketplace.t.sol
├─ script/
│  └─ Deploy.s.sol
└─ README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚙️ Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge init day-26-nft-marketplace
&lt;span class="nb"&gt;cd &lt;/span&gt;day-26-nft-marketplace
forge &lt;span class="nb"&gt;install &lt;/span&gt;OpenZeppelin/openzeppelin-contracts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;foundry.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[default]&lt;/span&gt;
&lt;span class="py"&gt;src&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"src"&lt;/span&gt;
&lt;span class="py"&gt;out&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"out"&lt;/span&gt;
&lt;span class="py"&gt;libs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;tests&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test"&lt;/span&gt;
&lt;span class="py"&gt;remappings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="py"&gt;["openzeppelin/&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;lib/openzeppelin-contracts/&lt;/span&gt;&lt;span class="s"&gt;"]&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧩 Step 1 — Create the NFT Contract (ERC-721 + Royalties)
&lt;/h2&gt;

&lt;p&gt;We’ll create an NFT collection with ERC-2981 (royalty) support.&lt;/p&gt;

&lt;p&gt;📄 &lt;strong&gt;src/NFTCollection.sol&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "openzeppelin/token/ERC721/ERC721.sol";
import "openzeppelin/access/Ownable.sol";
import "openzeppelin/token/common/ERC2981.sol";
import "openzeppelin/utils/Counters.sol";

contract NFTCollection is ERC721, ERC2981, Ownable {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIdCounter;

    string private _baseTokenURI;

    event Minted(address indexed to, uint256 indexed tokenId);

    constructor(string memory name_, string memory symbol_, string memory baseURI_)
        ERC721(name_, symbol_)
    {
        _baseTokenURI = baseURI_;
    }

    function mint(address to, uint96 royaltyBps) external onlyOwner returns (uint256) {
        _tokenIdCounter.increment();
        uint256 tokenId = _tokenIdCounter.current();
        _safeMint(to, tokenId);
        if (royaltyBps &amp;gt; 0) {
            _setTokenRoyalty(tokenId, owner(), royaltyBps);
        }
        emit Minted(to, tokenId);
        return tokenId;
    }

    function setDefaultRoyalty(address receiver, uint96 feeNumerator) external onlyOwner {
        _setDefaultRoyalty(receiver, feeNumerator);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721, ERC2981)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

    function _baseURI() internal view override returns (string memory) {
        return _baseTokenURI;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mint NFTs with optional per-token royalty.&lt;/li&gt;
&lt;li&gt;Default royalty for all tokens (via &lt;code&gt;ERC2981&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Each token has metadata base URI.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛒 Step 2 — Build the Marketplace Smart Contract
&lt;/h2&gt;

&lt;p&gt;Now, let’s create a marketplace to &lt;strong&gt;list, buy, and cancel&lt;/strong&gt; NFT sales.&lt;br&gt;
We’ll add &lt;strong&gt;marketplace fees&lt;/strong&gt; and &lt;strong&gt;royalty distribution&lt;/strong&gt; automatically.&lt;/p&gt;

&lt;p&gt;📄 &lt;strong&gt;src/NFTMarketplace.sol&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "openzeppelin/security/ReentrancyGuard.sol";
import "openzeppelin/token/ERC721/IERC721.sol";
import "openzeppelin/access/Ownable.sol";
import "openzeppelin/utils/Address.sol";
import "openzeppelin/token/common/ERC2981.sol";

contract NFTMarketplace is ReentrancyGuard, Ownable {
    using Address for address payable;

    struct Listing {
        address seller;
        uint256 price;
    }

    mapping(address =&amp;gt; mapping(uint256 =&amp;gt; Listing)) public listings;

    uint96 public marketplaceFeeBps;
    uint96 public constant FEE_DENOMINATOR = 10000;

    event Listed(address indexed nft, uint256 indexed tokenId, address indexed seller, uint256 price);
    event Cancelled(address indexed nft, uint256 indexed tokenId);
    event Bought(address indexed nft, uint256 indexed tokenId, address indexed buyer, uint256 price);

    constructor(uint96 _feeBps) {
        marketplaceFeeBps = _feeBps; // 250 = 2.5%
    }

    function list(address nft, uint256 tokenId, uint256 price) external nonReentrant {
        require(price &amp;gt; 0, "Price must be &amp;gt; 0");
        IERC721 token = IERC721(nft);
        require(token.ownerOf(tokenId) == msg.sender, "Not owner");
        require(token.getApproved(tokenId) == address(this) ||
                token.isApprovedForAll(msg.sender, address(this)), "Not approved");

        listings[nft][tokenId] = Listing(msg.sender, price);
        emit Listed(nft, tokenId, msg.sender, price);
    }

    function cancel(address nft, uint256 tokenId) external nonReentrant {
        Listing memory l = listings[nft][tokenId];
        require(l.seller == msg.sender, "Not seller");
        delete listings[nft][tokenId];
        emit Cancelled(nft, tokenId);
    }

    function buy(address nft, uint256 tokenId) external payable nonReentrant {
        Listing memory l = listings[nft][tokenId];
        require(l.price &amp;gt; 0, "Not listed");
        require(msg.value == l.price, "Wrong value");

        delete listings[nft][tokenId];

        uint256 fee = (msg.value * marketplaceFeeBps) / FEE_DENOMINATOR;
        uint256 remaining = msg.value - fee;

        (address royaltyReceiver, uint256 royaltyAmount) =
            _getRoyaltyInfo(nft, tokenId, msg.value);

        if (royaltyReceiver != address(0) &amp;amp;&amp;amp; royaltyAmount &amp;gt; 0) {
            if (royaltyAmount &amp;gt; remaining) royaltyAmount = remaining;
            remaining -= royaltyAmount;
            payable(royaltyReceiver).sendValue(royaltyAmount);
        }

        payable(l.seller).sendValue(remaining);
        payable(owner()).sendValue(fee);

        IERC721(nft).safeTransferFrom(l.seller, msg.sender, tokenId);

        emit Bought(nft, tokenId, msg.sender, msg.value);
    }

    function _getRoyaltyInfo(address nft, uint256 tokenId, uint256 price)
        internal
        view
        returns (address, uint256)
    {
        try ERC2981(nft).royaltyInfo(tokenId, price)
            returns (address receiver, uint256 amount)
        {
            return (receiver, amount);
        } catch {
            return (address(0), 0);
        }
    }

    receive() external payable {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Key Logic:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sellers list NFTs after approval.&lt;/li&gt;
&lt;li&gt;Buyers send ETH to buy NFTs.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Marketplace automatically splits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Creator royalty (ERC2981)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Marketplace fee&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seller payout&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Step 3 — Test the Marketplace (Foundry)
&lt;/h2&gt;

&lt;p&gt;📄 &lt;strong&gt;test/Marketplace.t.sol&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "forge-std/Test.sol";
import "../src/NFTCollection.sol";
import "../src/NFTMarketplace.sol";

contract MarketplaceTest is Test {
    NFTCollection nft;
    NFTMarketplace market;

    address owner = address(0xABCD);
    address seller = address(0xBEEF);
    address buyer = address(0xCAFE);

    function setUp() public {
        vm.startPrank(owner);
        nft = new NFTCollection("MyNFT", "MNFT", "ipfs://base/");
        market = new NFTMarketplace(250); // 2.5%
        nft.mint(seller, 500); // 5% royalty
        vm.stopPrank();
    }

    function testBuyNFT() public {
        vm.prank(seller);
        nft.approve(address(market), 1);
        vm.prank(seller);
        market.list(address(nft), 1, 1 ether);

        vm.deal(buyer, 2 ether);
        vm.prank(buyer);
        market.buy{value: 1 ether}(address(nft), 1);

        assertEq(nft.ownerOf(1), buyer);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Run tests:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Step 4 — Deploy the Contracts
&lt;/h2&gt;

&lt;p&gt;📄 &lt;strong&gt;script/Deploy.s.sol&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "forge-std/Script.sol";
import "../src/NFTCollection.sol";
import "../src/NFTMarketplace.sol";

contract Deploy is Script {
    function run() external {
        vm.startBroadcast();

        NFTCollection nft = new NFTCollection("MyNFT", "MNFT", "ipfs://base/");
        NFTMarketplace market = new NFTMarketplace(250);

        nft.setDefaultRoyalty(msg.sender, 200);

        vm.stopBroadcast();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy using Foundry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge script script/Deploy.s.sol &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;--private-key&lt;/span&gt; &amp;lt;YOUR_PRIVATE_KEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💰 Example Flow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Owner&lt;/strong&gt; deploys &lt;code&gt;NFTCollection&lt;/code&gt; &amp;amp; &lt;code&gt;NFTMarketplace&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creator&lt;/strong&gt; mints NFTs with 5% royalty.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seller&lt;/strong&gt; lists NFT for 1 ETH.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buyer&lt;/strong&gt; buys NFT:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;2.5% → Marketplace owner&lt;/li&gt;
&lt;li&gt;5% → Creator (royalty)&lt;/li&gt;
&lt;li&gt;92.5% → Seller&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything is &lt;strong&gt;on-chain&lt;/strong&gt;, transparent, and automatic 💫&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Security Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Reentrancy protection (&lt;code&gt;nonReentrant&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Checks-Effects-Interactions pattern&lt;/li&gt;
&lt;li&gt;Royalties capped (no overpayment)&lt;/li&gt;
&lt;li&gt;Only seller can cancel listings&lt;/li&gt;
&lt;li&gt;Funds transferred securely via &lt;code&gt;Address.sendValue&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Future Enhancements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Add ERC-20 token payments (e.g., USDC)&lt;/li&gt;
&lt;li&gt;Add auction and bidding system&lt;/li&gt;
&lt;li&gt;Build React frontend with Ethers.js&lt;/li&gt;
&lt;li&gt;Integrate The Graph for indexing listings&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Concepts Covered
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ERC-721 &amp;amp; ERC-2981 standards&lt;/li&gt;
&lt;li&gt;Royalty mechanism&lt;/li&gt;
&lt;li&gt;Marketplace fee handling&lt;/li&gt;
&lt;li&gt;Secure ETH transfers&lt;/li&gt;
&lt;li&gt;Foundry-based testing&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;You just built your &lt;strong&gt;own decentralized NFT Marketplace&lt;/strong&gt; — the foundation of OpenSea-like platforms.&lt;br&gt;
Now you understand how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage NFT listings and trades&lt;/li&gt;
&lt;li&gt;Handle royalties automatically&lt;/li&gt;
&lt;li&gt;Keep trades secure and transparent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your smart contracts handle &lt;strong&gt;trading, royalties, and fees — all without intermediaries!&lt;/strong&gt; 🚀&lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Connect With Me
&lt;/h2&gt;

&lt;p&gt;If you found this useful — drop a 💬 comment or ❤️ like!&lt;br&gt;
Let’s connect 👇&lt;br&gt;
&lt;strong&gt;🧑‍💻 Saurav Kumar&lt;/strong&gt;&lt;br&gt;
💼 &lt;a href="https://www.linkedin.com/in/sauravkumar8178" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
🧵 &lt;a href="https://twitter.com/sauravkumar8178" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt;&lt;br&gt;
📚 &lt;a href="https://dev.to/sauravkumar8178"&gt;More #30DaysOfSolidity Posts&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>security</category>
      <category>web3</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🧮 Day 25 of #30DaysOfSolidity — Build an Automated Market Maker (AMM) 💧</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Wed, 29 Oct 2025 17:10:53 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/day-25-of-30daysofsolidity-build-an-automated-market-maker-amm-1n60</link>
      <guid>https://forem.com/sauravkumar8178/day-25-of-30daysofsolidity-build-an-automated-market-maker-amm-1n60</guid>
      <description>&lt;p&gt;Welcome to &lt;strong&gt;Day 25&lt;/strong&gt; of the &lt;strong&gt;#30DaysOfSolidity&lt;/strong&gt; challenge!&lt;br&gt;
Today, we’ll build a &lt;strong&gt;decentralized Automated Market Maker (AMM)&lt;/strong&gt; — the core engine behind protocols like &lt;strong&gt;Uniswap&lt;/strong&gt; and &lt;strong&gt;Balancer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You’ll learn how to create a &lt;strong&gt;liquidity pool&lt;/strong&gt;, &lt;strong&gt;calculate swap prices&lt;/strong&gt;, and &lt;strong&gt;enable token trading&lt;/strong&gt; without an order book — all using &lt;strong&gt;Solidity&lt;/strong&gt; and &lt;strong&gt;Foundry&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧠 What is an Automated Market Maker (AMM)?
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;AMM&lt;/strong&gt; is a decentralized exchange mechanism that uses &lt;strong&gt;liquidity pools&lt;/strong&gt; instead of buyers and sellers.&lt;br&gt;
Users provide liquidity (token pairs) and earn fees when others trade using the pool.&lt;/p&gt;

&lt;p&gt;It uses the &lt;strong&gt;constant product formula&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;[&lt;br&gt;
x * y = k&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;x&lt;/code&gt; = reserve of Token A&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;y&lt;/code&gt; = reserve of Token B&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;k&lt;/code&gt; = constant (liquidity)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures the pool stays balanced after every trade.&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚙️ Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Solidity v0.8.20&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foundry&lt;/strong&gt; (for testing and scripting)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ERC20 Tokens&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom AMM Smart Contracts&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🏗️ Project Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Initialize Foundry Project&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge init day-25-amm
&lt;span class="nb"&gt;cd &lt;/span&gt;day-25-amm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Project Structure&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;day-25-amm/
├─ src/
│  ├─ AMMFactory.sol
│  ├─ AMMPair.sol
│  ├─ MockERC20.sol
│  └─ interfaces/IERC20Minimal.sol
├─ script/
│  ├─ Deploy.s.sol
│  └─ AddLiquidity.s.sol
├─ test/
│  ├─ Pair.t.sol
├─ lib/
│  └─ (optional dependencies)
├─ foundry.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💡 Step 3: Create a Minimal ERC20 Token
&lt;/h2&gt;

&lt;p&gt;We’ll use a mock ERC20 token for testing the AMM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📄 &lt;code&gt;src/MockERC20.sol&lt;/code&gt;&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "./interfaces/IERC20Minimal.sol";

contract MockERC20 is IERC20Minimal {
    string public name;
    string public symbol;
    uint8 public decimals = 18;
    uint256 public override totalSupply;

    mapping(address =&amp;gt; uint256) public override balanceOf;
    mapping(address =&amp;gt; mapping(address =&amp;gt; uint256)) public override allowance;

    constructor(string memory _name, string memory _symbol, uint256 _initialSupply) {
        name = _name;
        symbol = _symbol;
        _mint(msg.sender, _initialSupply);
    }

    function transfer(address to, uint256 value) public override returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function approve(address spender, uint256 value) public override returns (bool) {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) public override returns (bool) {
        uint256 allowed = allowance[from][msg.sender];
        require(allowed &amp;gt;= value, "Insufficient allowance");
        allowance[from][msg.sender] = allowed - value;
        _transfer(from, to, value);
        return true;
    }

    function _transfer(address from, address to, uint256 value) internal {
        require(balanceOf[from] &amp;gt;= value, "Insufficient balance");
        balanceOf[from] -= value;
        balanceOf[to] += value;
        emit Transfer(from, to, value);
    }

    function _mint(address to, uint256 value) internal {
        totalSupply += value;
        balanceOf[to] += value;
        emit Transfer(address(0), to, value);
    }

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧮 Step 4: Build the AMM Pair Contract
&lt;/h2&gt;

&lt;p&gt;This contract manages the &lt;strong&gt;liquidity pool&lt;/strong&gt;, &lt;strong&gt;swaps&lt;/strong&gt;, and &lt;strong&gt;reserve balances&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📄 &lt;code&gt;src/AMMPair.sol&lt;/code&gt;&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "./interfaces/IERC20Minimal.sol";

contract AMMPair {
    IERC20Minimal public token0;
    IERC20Minimal public token1;

    uint256 public reserve0;
    uint256 public reserve1;

    constructor(address _token0, address _token1) {
        token0 = IERC20Minimal(_token0);
        token1 = IERC20Minimal(_token1);
    }

    function addLiquidity(uint256 amount0, uint256 amount1) external {
        require(amount0 &amp;gt; 0 &amp;amp;&amp;amp; amount1 &amp;gt; 0, "Invalid amount");
        token0.transferFrom(msg.sender, address(this), amount0);
        token1.transferFrom(msg.sender, address(this), amount1);

        reserve0 += amount0;
        reserve1 += amount1;
    }

    function getAmountOut(uint256 amountIn, address inputToken) public view returns (uint256 amountOut) {
        require(amountIn &amp;gt; 0, "Invalid input");
        bool isToken0 = inputToken == address(token0);
        (uint256 reserveIn, uint256 reserveOut) = isToken0 ? (reserve0, reserve1) : (reserve1, reserve0);

        uint256 amountInWithFee = amountIn * 997;
        amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);
    }

    function swap(uint256 amountIn, address inputToken) external {
        require(amountIn &amp;gt; 0, "Invalid input");
        bool isToken0 = inputToken == address(token0);

        IERC20Minimal input = isToken0 ? token0 : token1;
        IERC20Minimal output = isToken0 ? token1 : token0;

        uint256 amountOut = getAmountOut(amountIn, inputToken);
        require(amountOut &amp;gt; 0, "Insufficient output");

        input.transferFrom(msg.sender, address(this), amountIn);
        output.transfer(msg.sender, amountOut);

        if (isToken0) {
            reserve0 += amountIn;
            reserve1 -= amountOut;
        } else {
            reserve1 += amountIn;
            reserve0 -= amountOut;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏭 Step 5: Create AMM Factory
&lt;/h2&gt;

&lt;p&gt;The factory helps create new token pairs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📄 &lt;code&gt;src/AMMFactory.sol&lt;/code&gt;&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "./AMMPair.sol";

contract AMMFactory {
    mapping(address =&amp;gt; mapping(address =&amp;gt; address)) public getPair;
    address[] public allPairs;

    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    function createPair(address tokenA, address tokenB) external returns (address pair) {
        require(tokenA != tokenB, "Identical tokens");
        require(getPair[tokenA][tokenB] == address(0), "Pair exists");

        AMMPair newPair = new AMMPair(tokenA, tokenB);
        pair = address(newPair);

        getPair[tokenA][tokenB] = pair;
        getPair[tokenB][tokenA] = pair;
        allPairs.push(pair);

        emit PairCreated(tokenA, tokenB, pair, allPairs.length);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Step 6: Deployment Script
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📄 &lt;code&gt;script/Deploy.s.sol&lt;/code&gt;&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Script.sol";
import "../src/AMMFactory.sol";
import "../src/MockERC20.sol";

contract DeployScript is Script {
    function run() external {
        vm.startBroadcast();

        MockERC20 tokenA = new MockERC20("TokenA", "TKA", 1_000_000 ether);
        MockERC20 tokenB = new MockERC20("TokenB", "TKB", 1_000_000 ether);
        AMMFactory factory = new AMMFactory();

        factory.createPair(address(tokenA), address(tokenB));

        vm.stopBroadcast();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge script script/Deploy.s.sol &lt;span class="nt"&gt;--broadcast&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💧 Step 7: Add Liquidity Script
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📄 &lt;code&gt;script/AddLiquidity.s.sol&lt;/code&gt;&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Script.sol";
import "../src/AMMPair.sol";
import "../src/MockERC20.sol";

contract AddLiquidityScript is Script {
    function run(address tokenA, address tokenB, address pairAddress) external {
        vm.startBroadcast();

        AMMPair pair = AMMPair(pairAddress);

        MockERC20(tokenA).approve(address(pair), 100 ether);
        MockERC20(tokenB).approve(address(pair), 100 ether);

        pair.addLiquidity(100 ether, 100 ether);

        vm.stopBroadcast();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Step 8: Testing with Foundry
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📄 &lt;code&gt;test/Pair.t.sol&lt;/code&gt;&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;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "../src/AMMPair.sol";
import "../src/MockERC20.sol";

contract PairTest is Test {
    AMMPair pair;
    MockERC20 tokenA;
    MockERC20 tokenB;

    function setUp() public {
        tokenA = new MockERC20("TokenA", "TKA", 1_000_000 ether);
        tokenB = new MockERC20("TokenB", "TKB", 1_000_000 ether);
        pair = new AMMPair(address(tokenA), address(tokenB));

        tokenA.approve(address(pair), type(uint256).max);
        tokenB.approve(address(pair), type(uint256).max);
    }

    function testAddLiquidity() public {
        pair.addLiquidity(100 ether, 200 ether);
        assertEq(pair.reserve0(), 100 ether);
        assertEq(pair.reserve1(), 200 ether);
    }

    function testSwap() public {
        pair.addLiquidity(100 ether, 100 ether);
        tokenA.transfer(address(1), 50 ether);
        vm.prank(address(1));
        tokenA.approve(address(pair), 10 ether);
        vm.prank(address(1));
        pair.swap(10 ether, address(tokenA));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run tests:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 Key Learning Points
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Learned about liquidity pools and AMM logic&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Implemented swap and reserve balance updates&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Used Foundry for testing and scripting&lt;/strong&gt;&lt;br&gt;
✅ &lt;strong&gt;Built a factory for creating multiple token pairs&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💫 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Congratulations! 🎉&lt;br&gt;
You’ve built a &lt;strong&gt;mini Uniswap&lt;/strong&gt; using Solidity and Foundry.&lt;/p&gt;

&lt;p&gt;This hands-on example helps you deeply understand how decentralized exchanges work under the hood — from &lt;strong&gt;adding liquidity&lt;/strong&gt; to &lt;strong&gt;executing token swaps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Next up: you can extend it by adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Liquidity tokens (LP tokens)&lt;/li&gt;
&lt;li&gt;Swap fees distribution&lt;/li&gt;
&lt;li&gt;Price oracles&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔗 GitHub Repository
&lt;/h3&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/sauravkumar8178/30-days-of-solidity-submissions/tree/main/submissions/sauravkumar8178/day-25-solidity" rel="noopener noreferrer"&gt;GitHub - Day 25 AMM Project&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 Join the Challenge
&lt;/h3&gt;

&lt;p&gt;Follow my &lt;strong&gt;&lt;a href="https://www.web3compass.xyz/challenge-calendar" rel="noopener noreferrer"&gt;#30DaysOfSolidity&lt;/a&gt;&lt;/strong&gt; journey and build your own DeFi stack step-by-step!&lt;br&gt;
Let’s make blockchain development fun and practical 🚀&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>web3</category>
      <category>ethereum</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🏦 Day 24 of #30DaysOfSolidity — Build a Secure Conditional Payments (Escrow) System in Solidity</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Wed, 29 Oct 2025 06:07:25 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/day-24-of-30daysofsolidity-build-a-secure-conditional-payments-escrow-system-in-solidity-4hm7</link>
      <guid>https://forem.com/sauravkumar8178/day-24-of-30daysofsolidity-build-a-secure-conditional-payments-escrow-system-in-solidity-4hm7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Ever wondered how to make payments safe in decentralized marketplaces?&lt;/strong&gt;&lt;br&gt;
Today, we’re building a &lt;strong&gt;Secure Escrow System&lt;/strong&gt; — a smart contract that holds funds until both parties fulfill agreed conditions.&lt;/p&gt;

&lt;p&gt;It’s like a &lt;strong&gt;digital middleman&lt;/strong&gt;, ensuring funds are only released when everything goes right — or refunded safely in disputes.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What You’ll Learn
&lt;/h2&gt;

&lt;p&gt;✅ How to build a &lt;strong&gt;secure payment escrow&lt;/strong&gt; using Solidity&lt;br&gt;
✅ Handle &lt;strong&gt;ETH &amp;amp; ERC-20 tokens&lt;/strong&gt; safely&lt;br&gt;
✅ Manage &lt;strong&gt;disputes&lt;/strong&gt; with an arbiter&lt;br&gt;
✅ Protect funds with &lt;strong&gt;ReentrancyGuard&lt;/strong&gt; and &lt;strong&gt;SafeERC20&lt;/strong&gt;&lt;br&gt;
✅ Implement &lt;strong&gt;deadline-based resolution&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Concept Overview
&lt;/h2&gt;

&lt;p&gt;In traditional systems, platforms like Upwork or PayPal hold funds until both sides agree.&lt;br&gt;
On-chain, we can do the same — &lt;strong&gt;without trusting a central authority.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Roles involved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Buyer&lt;/strong&gt; – Deposits funds for the purchase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seller&lt;/strong&gt; – Delivers goods/services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arbiter&lt;/strong&gt; – Neutral party that resolves disputes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Buyer creates and funds an escrow.&lt;/li&gt;
&lt;li&gt;Seller delivers work.&lt;/li&gt;
&lt;li&gt;Buyer approves → funds go to seller.&lt;/li&gt;
&lt;li&gt;Dispute? → Arbiter decides release or refund.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🧱 Smart Contract: &lt;code&gt;Escrow.sol&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/*
Day 24 — Secure Conditional Payments (Escrow)
A system that holds funds until both parties agree, 
with support for ETH, ERC20, and dispute resolution.
*/

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Escrow is ReentrancyGuard, Ownable {
    using SafeERC20 for IERC20;

    enum Status { AWAITING_PAYMENT, AWAITING_DELIVERY, COMPLETE, DISPUTED, REFUNDED, CANCELLED }

    struct Agreement {
        address buyer;
        address seller;
        address arbiter;
        address token;
        uint256 amount;
        uint256 deadline;
        Status status;
        bool buyerApproved;
        bool sellerMarkedDelivered;
        uint256 createdAt;
    }

    uint256 public nextId;
    mapping(uint256 =&amp;gt; Agreement) public agreements;

    event EscrowCreated(uint256 indexed id, address indexed buyer, address indexed seller, address arbiter, address token, uint256 amount, uint256 deadline);
    event Funded(uint256 indexed id, address payer, uint256 amount);
    event BuyerApproved(uint256 indexed id, address indexed buyer);
    event DisputeRaised(uint256 indexed id, address indexed by);
    event Resolved(uint256 indexed id, address indexed arbiter, address to, uint256 amount);
    event Refunded(uint256 indexed id, address indexed to, uint256 amount);

    modifier onlyBuyer(uint256 id) {
        require(msg.sender == agreements[id].buyer, "only buyer");
        _;
    }

    modifier onlySeller(uint256 id) {
        require(msg.sender == agreements[id].seller, "only seller");
        _;
    }

    modifier onlyArbiter(uint256 id) {
        require(msg.sender == agreements[id].arbiter, "only arbiter");
        _;
    }

    modifier inStatus(uint256 id, Status s) {
        require(agreements[id].status == s, "invalid status");
        _;
    }

    constructor() {
        nextId = 1;
    }

    function createEscrow(address seller, address arbiter, address token, uint256 amount, uint256 deadline) external returns (uint256) {
        require(seller != address(0), "invalid seller");
        require(amount &amp;gt; 0, "amount&amp;gt;0");

        uint256 id = nextId++;
        agreements[id] = Agreement({
            buyer: msg.sender,
            seller: seller,
            arbiter: arbiter,
            token: token,
            amount: amount,
            deadline: deadline,
            status: Status.AWAITING_PAYMENT,
            buyerApproved: false,
            sellerMarkedDelivered: false,
            createdAt: block.timestamp
        });

        emit EscrowCreated(id, msg.sender, seller, arbiter, token, amount, deadline);
        return id;
    }

    function fundEscrowETH(uint256 id) external payable nonReentrant inStatus(id, Status.AWAITING_PAYMENT) {
        Agreement storage a = agreements[id];
        require(a.token == address(0), "not ETH");
        require(msg.sender == a.buyer, "only buyer");
        require(msg.value == a.amount, "wrong amount");
        a.status = Status.AWAITING_DELIVERY;
        emit Funded(id, msg.sender, msg.value);
    }

    function fundEscrowERC20(uint256 id) external nonReentrant inStatus(id, Status.AWAITING_PAYMENT) {
        Agreement storage a = agreements[id];
        require(a.token != address(0), "not ERC20");
        require(msg.sender == a.buyer, "only buyer");
        IERC20(a.token).safeTransferFrom(msg.sender, address(this), a.amount);
        a.status = Status.AWAITING_DELIVERY;
        emit Funded(id, msg.sender, a.amount);
    }

    function buyerApprove(uint256 id) external onlyBuyer(id) inStatus(id, Status.AWAITING_DELIVERY) nonReentrant {
        Agreement storage a = agreements[id];
        a.buyerApproved = true;
        a.status = Status.COMPLETE;
        _payout(a.token, a.seller, a.amount);
        emit BuyerApproved(id, msg.sender);
    }

    function raiseDispute(uint256 id) external onlyBuyer(id) inStatus(id, Status.AWAITING_DELIVERY) {
        agreements[id].status = Status.DISPUTED;
        emit DisputeRaised(id, msg.sender);
    }

    function arbiterResolve(uint256 id, bool releaseToSeller) external onlyArbiter(id) inStatus(id, Status.DISPUTED) nonReentrant {
        Agreement storage a = agreements[id];
        if (releaseToSeller) {
            a.status = Status.COMPLETE;
            _payout(a.token, a.seller, a.amount);
            emit Resolved(id, msg.sender, a.seller, a.amount);
        } else {
            a.status = Status.REFUNDED;
            _payout(a.token, a.buyer, a.amount);
            emit Refunded(id, a.buyer, a.amount);
        }
    }

    function claimAfterDeadline(uint256 id) external nonReentrant inStatus(id, Status.AWAITING_DELIVERY) {
        Agreement storage a = agreements[id];
        require(a.deadline != 0 &amp;amp;&amp;amp; block.timestamp &amp;gt; a.deadline, "deadline not passed");
        require(msg.sender == a.seller, "only seller");
        a.status = Status.COMPLETE;
        _payout(a.token, a.seller, a.amount);
        emit Resolved(id, address(0), a.seller, a.amount);
    }

    function _payout(address token, address to, uint256 amount) internal {
        if (token == address(0)) {
            (bool ok, ) = payable(to).call{value: amount}("");
            require(ok, "ETH transfer failed");
        } else {
            IERC20(token).safeTransfer(to, amount);
        }
    }

    receive() external payable {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Testing with Foundry
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📁 Folder Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;day-24-escrow/
 ├── src/
 │   └── Escrow.sol
 ├── test/
 │   └── Escrow.t.sol
 └── foundry.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧾 Test File (&lt;code&gt;Escrow.t.sol&lt;/code&gt;)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "../src/Escrow.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract DummyToken is ERC20 {
    constructor() ERC20("Dummy", "DUM") { _mint(msg.sender, 1_000_000e18); }
}

contract EscrowTest is Test {
    Escrow escrow;
    DummyToken token;
    address buyer = address(0xBEEF);
    address seller = address(0xCAFE);
    address arbiter = address(0xABCD);

    function setUp() public {
        escrow = new Escrow();
        token = new DummyToken();
        vm.deal(buyer, 2 ether);
    }

    function testEthEscrowFlow() public {
        vm.startPrank(buyer);
        uint256 id = escrow.createEscrow(seller, arbiter, address(0), 1 ether, 0);
        escrow.fundEscrowETH{value: 1 ether}(id);
        escrow.buyerApprove(id);
        vm.stopPrank();
    }

    function testERC20DisputeRefund() public {
        vm.startPrank(buyer);
        uint256 id = escrow.createEscrow(seller, arbiter, address(token), 100e18, 0);
        token.approve(address(escrow), 100e18);
        escrow.fundEscrowERC20(id);
        escrow.raiseDispute(id);
        vm.stopPrank();

        vm.prank(arbiter);
        escrow.arbiterResolve(id, false); // refund to buyer
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚡ Run Locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge init day-24-escrow
&lt;span class="nb"&gt;cd &lt;/span&gt;day-24-escrow
forge &lt;span class="nb"&gt;install &lt;/span&gt;OpenZeppelin/openzeppelin-contracts
forge build
forge &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-vv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔐 Security Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Protected by &lt;strong&gt;ReentrancyGuard&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ Safe token transfers via &lt;strong&gt;SafeERC20&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ Proper state checks with modifiers&lt;/li&gt;
&lt;li&gt;✅ Arbiter-based dispute resolution&lt;/li&gt;
&lt;li&gt;✅ Deadline system for inactive buyers&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧩 Possible Enhancements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;💸 Platform fees for escrow service&lt;/li&gt;
&lt;li&gt;⏱️ Multi-stage milestone releases&lt;/li&gt;
&lt;li&gt;🏛️ DAO-based arbitration&lt;/li&gt;
&lt;li&gt;🌐 Chainlink oracle for automated verification&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You built a &lt;strong&gt;trustless payment system&lt;/strong&gt; using Solidity.&lt;/li&gt;
&lt;li&gt;Learned how to &lt;strong&gt;handle disputes&lt;/strong&gt; safely.&lt;/li&gt;
&lt;li&gt;Applied &lt;strong&gt;security best practices&lt;/strong&gt; for real-world DeFi apps.&lt;/li&gt;
&lt;li&gt;Understood how &lt;strong&gt;conditional payments&lt;/strong&gt; power Web3 marketplaces.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏁 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This escrow contract is a cornerstone for &lt;strong&gt;decentralized marketplaces, freelance platforms, and P2P trades&lt;/strong&gt;.&lt;br&gt;
It teaches how to &lt;strong&gt;hold and release funds securely&lt;/strong&gt; using smart contracts.&lt;/p&gt;

&lt;p&gt;You now know how to implement &lt;strong&gt;secure, conditional payments on-chain&lt;/strong&gt; 💪&lt;/p&gt;

</description>
      <category>web3</category>
      <category>ethereum</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>💰 Day 23 of #30DaysOfSolidity — Build a DeFi Lending &amp; Borrowing System (Aave-like dApp)</title>
      <dc:creator>Saurav Kumar</dc:creator>
      <pubDate>Wed, 29 Oct 2025 05:53:59 +0000</pubDate>
      <link>https://forem.com/sauravkumar8178/day-23-of-30daysofsolidity-build-a-defi-lending-borrowing-system-aave-like-dapp-3j78</link>
      <guid>https://forem.com/sauravkumar8178/day-23-of-30daysofsolidity-build-a-defi-lending-borrowing-system-aave-like-dapp-3j78</guid>
      <description>&lt;p&gt;Welcome to &lt;strong&gt;Day 23 of #30DaysOfSolidity&lt;/strong&gt;!&lt;br&gt;
Today, we’re diving into one of the most &lt;strong&gt;powerful DeFi concepts&lt;/strong&gt; — &lt;em&gt;Lending and Borrowing&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This project will show how to build a &lt;strong&gt;mini Aave-style lending pool&lt;/strong&gt; using &lt;strong&gt;Solidity&lt;/strong&gt; and &lt;strong&gt;Foundry&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You’ll learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🏦 How deposits (collateral) and borrowing work&lt;/li&gt;
&lt;li&gt;💸 How to calculate dynamic interest&lt;/li&gt;
&lt;li&gt;⚖️ How to check collateral ratios &amp;amp; trigger liquidation&lt;/li&gt;
&lt;li&gt;🔒 How DeFi banks enforce loans automatically&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🏗️ Project Structure
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;foundry-project/
├─ src/
│  ├─ ERC20Mock.sol
│  ├─ IPriceOracle.sol
│  ├─ InterestRateModel.sol
│  └─ LendingPool.sol
├─ test/
│  ├─ LendingPool.t.sol
├─ remappings.txt
├─ foundry.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⚙️ Setup
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge init foundry-project
&lt;span class="nb"&gt;cd &lt;/span&gt;foundry-project
forge &lt;span class="nb"&gt;install &lt;/span&gt;OpenZeppelin/openzeppelin-contracts &lt;span class="nt"&gt;--no-commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🧩 1. ERC20Mock.sol
&lt;/h2&gt;

&lt;p&gt;A simple ERC-20 token for testing deposits and loans.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "openzeppelin-contracts/token/ERC20/ERC20.sol";

contract ERC20Mock is ERC20 {
    constructor(string memory name, string memory symbol, uint256 initialSupply)
        ERC20(name, symbol)
    {
        _mint(msg.sender, initialSupply);
    }

    function mint(address to, uint256 amount) external {
        _mint(to, amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 2. IPriceOracle.sol
&lt;/h2&gt;

&lt;p&gt;Interface for an external or mock price oracle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IPriceOracle {
    function getPrice(address token) external view returns (uint256);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💹 3. InterestRateModel.sol
&lt;/h2&gt;

&lt;p&gt;Implements a &lt;strong&gt;simple dynamic interest model&lt;/strong&gt; — interest grows with utilization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract InterestRateModel {
    uint256 public baseRate; // e.g. 2% annual
    uint256 public slope;    // increase per utilization %

    constructor(uint256 _baseRate, uint256 _slope) {
        baseRate = _baseRate;
        slope = _slope;
    }

    function getBorrowRate(uint256 utilization) external view returns (uint256) {
        // utilization is scaled to 1e18 (e.g. 0.5 = 50%)
        return baseRate + (slope * utilization) / 1e18;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏦 4. LendingPool.sol
&lt;/h2&gt;

&lt;p&gt;Core smart contract handling deposits, borrowing, interest, and liquidation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "./ERC20Mock.sol";
import "./IPriceOracle.sol";
import "./InterestRateModel.sol";

contract LendingPool {
    struct Position {
        uint256 collateral;
        uint256 debt;
        uint256 lastUpdate;
    }

    mapping(address =&amp;gt; Position) public positions;

    ERC20Mock public token;
    IPriceOracle public oracle;
    InterestRateModel public rateModel;

    uint256 public collateralFactor = 75; // 75%
    uint256 public liquidationThreshold = 85; // 85%

    constructor(address _token, address _oracle, address _rateModel) {
        token = ERC20Mock(_token);
        oracle = IPriceOracle(_oracle);
        rateModel = InterestRateModel(_rateModel);
    }

    // --- Deposit ---
    function depositCollateral(uint256 amount) external {
        require(amount &amp;gt; 0, "Invalid amount");
        token.transferFrom(msg.sender, address(this), amount);
        positions[msg.sender].collateral += amount;
        positions[msg.sender].lastUpdate = block.timestamp;
    }

    // --- Borrow ---
    function borrow(uint256 amount) external {
        _accrueInterest(msg.sender);

        uint256 price = oracle.getPrice(address(token)); // token price in USD (1e18)
        uint256 maxBorrow = (positions[msg.sender].collateral * price * collateralFactor) / (100 * 1e18);

        require(positions[msg.sender].debt + amount &amp;lt;= maxBorrow, "Exceeds limit");

        positions[msg.sender].debt += amount;
        token.transfer(msg.sender, amount);
        positions[msg.sender].lastUpdate = block.timestamp;
    }

    // --- Repay ---
    function repay(uint256 amount) external {
        require(amount &amp;gt; 0, "Invalid amount");
        token.transferFrom(msg.sender, address(this), amount);

        _accrueInterest(msg.sender);

        if (amount &amp;gt;= positions[msg.sender].debt) {
            positions[msg.sender].debt = 0;
        } else {
            positions[msg.sender].debt -= amount;
        }

        positions[msg.sender].lastUpdate = block.timestamp;
    }

    // --- Liquidation ---
    function liquidate(address user) external {
        _accrueInterest(user);
        uint256 price = oracle.getPrice(address(token));
        uint256 maxAllowedDebt = (positions[user].collateral * price * liquidationThreshold) / (100 * 1e18);

        require(positions[user].debt &amp;gt; maxAllowedDebt, "Position healthy");

        token.transfer(msg.sender, positions[user].collateral); // reward liquidator
        delete positions[user];
    }

    // --- Internal interest accrual ---
    function _accrueInterest(address user) internal {
        Position storage p = positions[user];
        if (p.debt == 0 || p.lastUpdate == 0) return;

        uint256 timeElapsed = block.timestamp - p.lastUpdate;
        uint256 utilization = (p.debt * 1e18) / (p.collateral + 1);
        uint256 rate = rateModel.getBorrowRate(utilization); // % per year

        uint256 interest = (p.debt * rate * timeElapsed) / (365 days * 100);
        p.debt += interest;
        p.lastUpdate = block.timestamp;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 5. test/LendingPool.t.sol
&lt;/h2&gt;

&lt;p&gt;Simulate deposits, borrows, repayments, and liquidation in Foundry.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "../src/LendingPool.sol";

contract MockOracle is IPriceOracle {
    function getPrice(address) external pure override returns (uint256) {
        return 1e18; // 1 token = 1 USD
    }
}

contract LendingPoolTest is Test {
    ERC20Mock token;
    LendingPool pool;
    InterestRateModel rateModel;
    MockOracle oracle;

    address user = address(0x123);
    address liquidator = address(0x456);

    function setUp() public {
        token = new ERC20Mock("Mock Token", "MCK", 1_000_000 ether);
        oracle = new MockOracle();
        rateModel = new InterestRateModel(2, 10);
        pool = new LendingPool(address(token), address(oracle), address(rateModel));

        token.mint(user, 1000 ether);
        vm.startPrank(user);
        token.approve(address(pool), type(uint256).max);
        vm.stopPrank();
    }

    function testDepositAndBorrow() public {
        vm.startPrank(user);
        pool.depositCollateral(500 ether);
        pool.borrow(200 ether);
        vm.stopPrank();

        LendingPool.Position memory pos = pool.positions(user);
        assertEq(pos.collateral, 500 ether);
        assertGt(pos.debt, 0);
    }

    function testRepay() public {
        vm.startPrank(user);
        pool.depositCollateral(500 ether);
        pool.borrow(200 ether);
        pool.repay(50 ether);
        vm.stopPrank();

        assertLt(pool.positions(user).debt, 200 ether);
    }

    function testLiquidation() public {
        vm.startPrank(user);
        pool.depositCollateral(500 ether);
        pool.borrow(400 ether);
        vm.stopPrank();

        // Simulate price drop (collateral value ↓)
        vm.prank(liquidator);
        pool.liquidate(user);

        assertEq(pool.positions(user).collateral, 0);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚙️ foundry.toml
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[profile.default]&lt;/span&gt;
&lt;span class="py"&gt;src&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"src"&lt;/span&gt;
&lt;span class="py"&gt;out&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"out"&lt;/span&gt;
&lt;span class="py"&gt;libs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Run the Project
&lt;/h2&gt;



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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧠 Key Concepts Recap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Collateral&lt;/td&gt;
&lt;td&gt;Asset locked to secure a loan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collateral Factor&lt;/td&gt;
&lt;td&gt;% of collateral that can be borrowed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interest Rate&lt;/td&gt;
&lt;td&gt;Grows dynamically with pool utilization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Liquidation&lt;/td&gt;
&lt;td&gt;Triggered when user’s debt &amp;gt; allowed threshold&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💡 Real-World Inspiration
&lt;/h2&gt;

&lt;p&gt;This is a simplified version of &lt;strong&gt;Aave&lt;/strong&gt; or &lt;strong&gt;Compound&lt;/strong&gt;, both of which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use on-chain oracles (Chainlink) for price feeds&lt;/li&gt;
&lt;li&gt;Implement advanced interest models&lt;/li&gt;
&lt;li&gt;Support multiple token markets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ve just built the &lt;strong&gt;foundation of a DeFi lending protocol&lt;/strong&gt; 🏦✨&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 Next Up
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Day 24 → Secure Escrow System 🔒&lt;/strong&gt;&lt;br&gt;
We’ll build a safe smart contract for conditional payments.&lt;/p&gt;

&lt;p&gt;Follow my journey on &lt;a href="https://dev.to/sauravkumar8178"&gt;Dev.to&lt;/a&gt; 💫&lt;br&gt;
and tag &lt;strong&gt;&lt;a href="https://www.web3compass.xyz/challenge-calendar" rel="noopener noreferrer"&gt;#30DaysOfSolidity&lt;/a&gt;&lt;/strong&gt; to inspire more builders.&lt;/p&gt;

&lt;p&gt;🔗 Full Source Code&lt;/p&gt;

&lt;p&gt;🧱 GitHub: &lt;a href="https://github.com/sauravkumar8178/30-days-of-solidity-submissions/tree/main/submissions/sauravkumar8178/day-23-solidity" rel="noopener noreferrer"&gt;Day23-Lending-Borrowing&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>tutorial</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
