<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: N DIVIJ</title>
    <description>The latest articles on DEV Community by N DIVIJ (@n45div).</description>
    <link>https://dev.to/n45div</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1116704%2Fc2517b17-e373-401c-b3d4-047103c31fa6.jpeg</url>
      <title>DEV Community: N DIVIJ</title>
      <link>https://dev.to/n45div</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/n45div"/>
    <language>en</language>
    <item>
      <title>Building Missio: An Evidence-Bound Remediation Agent with SigNoz</title>
      <dc:creator>N DIVIJ</dc:creator>
      <pubDate>Sun, 26 Jul 2026 11:51:55 +0000</pubDate>
      <link>https://dev.to/n45div/building-missio-an-evidence-bound-remediation-agent-with-signoz-47</link>
      <guid>https://dev.to/n45div/building-missio-an-evidence-bound-remediation-agent-with-signoz-47</guid>
      <description>&lt;p&gt;A production error is exactly when an AI agent should be least creative.&lt;/p&gt;

&lt;p&gt;That sentence became the design rule behind Missio, a terminal mission control system I built for the Agents of SigNoz hackathon. Missio starts with a real incident reported in Slack, reconstructs what happened from SigNoz, finds the exact source revision that produced the failure, asks an agent for a tightly bounded change, and opens a draft pull request only after a human approves the action.&lt;/p&gt;

&lt;p&gt;The entire journey stays visible in one Rust TUI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SIGNAL → EVIDENCE → CODE → PATCH → HUMAN → PR → CI → HANDOFF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a dashboard with an AI summary beside it. Every stage represents something the system has actually observed or completed. If evidence is missing, the mission stops. If GitHub cannot&lt;br&gt;
resolve the production revision, it stops. If the model returns an unsafe patch, it stops.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Incident Agents Need Evidence, Not Confidence
&lt;/h2&gt;

&lt;p&gt;Observability tools are already good at showing that a request failed. The harder question is what an agent should be allowed to do next.&lt;/p&gt;

&lt;p&gt;An error message alone does not establish which code was deployed. A repository's default branch may have moved since the failure. A model can produce a convincing explanation using the wrong version of a file. It can also quietly fill missing context with assumptions.&lt;/p&gt;

&lt;p&gt;I wanted the opposite behavior. Missio should be useful only when it can build a chain from a production signal to a specific piece of source code. The agent's job is to reason inside that chain, not invent one.&lt;/p&gt;

&lt;p&gt;That made SigNoz the evidence system of record rather than a decorative integration.&lt;/p&gt;
&lt;h2&gt;
  
  
  Turning a Real Checkout Failure Into a Mission
&lt;/h2&gt;

&lt;p&gt;For the demo, I use an instrumented checkout service. A bad discount request reaches a real HTTP endpoint and produces a failing OpenTelemetry span. The span is exported to SigNoz with the normal service and error fields, plus the details Missio needs to connect runtime behavior to source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The affected resource;&lt;/li&gt;
&lt;li&gt;The environment;&lt;/li&gt;
&lt;li&gt;The code file and function;&lt;/li&gt;
&lt;li&gt;The repository URL;&lt;/li&gt;
&lt;li&gt;The full Git commit running in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then an operator opens the incident from an allowlisted Slack channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/missio-sev SEV1 service production/checkout checkout requests are failing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Slack is only the admission point. The message does not tell the agent what the root cause is, and Missio does not treat the wording as evidence. It uses the resource and incident window to query the corresponding telemetry in SigNoz.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Indexing Delay That Changed the Design
&lt;/h2&gt;

&lt;p&gt;The most useful lesson from building Missio did not come from reading documentation. It came from a demo that failed even though every individual component appeared healthy.&lt;/p&gt;

&lt;p&gt;The checkout service successfully exported its span. SigNoz accepted the telemetry. But Missio queried immediately and received no matching rows. A short time later, the same query returned the failure exactly as expected.&lt;/p&gt;

&lt;p&gt;Ingestion acceptance and query availability are not the same moment.&lt;/p&gt;

&lt;p&gt;That distinction sounds small, but it changes the behavior of an autonomous workflow. If an empty first response means “there was no incident,” the agent can discard a genuine production failure.&lt;/p&gt;

&lt;p&gt;If the system waits forever, the operator cannot tell whether it is making progress.&lt;/p&gt;

&lt;p&gt;Missio now performs bounded evidence acquisition and makes the wait visible in the TUI. It retries for a limited period while SigNoz indexes the span. If a valid evidence bundle still cannot be formed, the EVIDENCE stage fails closed. It never replaces missing telemetry with a fabricated&lt;br&gt;
incident just to keep the animation moving.&lt;/p&gt;

&lt;p&gt;This was also why I kept the signal horizon at the bottom of the interface. The operator can see whether Missio is listening, acquiring evidence, or holding because the observation is incomplete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Letting Telemetry Choose the Source
&lt;/h2&gt;

&lt;p&gt;Once the trace is available, Missio extracts the repository and the full deployed commit from the span. That commit matters more than the current state of the default branch: it identifies the code that actually produced the observed failure.&lt;/p&gt;

&lt;p&gt;Missio reads the repository tree at that immutable revision and selects source linked to the observed code location. In a monorepo, it can keep the investigation inside the affected service. Only that bounded context reaches the agent.&lt;/p&gt;

&lt;p&gt;This gives the model a much more honest question:&lt;/p&gt;

&lt;p&gt;Given this observed failure and the exact source that produced it, is there enough evidence for a small fix?&lt;/p&gt;

&lt;p&gt;The model can either hold the mission or propose replacement content for source it was given. It cannot add an unrelated file, edit the CI workflow, reach outside the service boundary, or claim that an external action succeeded. Those decisions are enforced by Rust after the model responds.&lt;/p&gt;

&lt;p&gt;Missio uses Rig for the agent runtime and an explicitly configured model through OpenRouter. The model never receives Slack, SigNoz, or GitHub credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the TUI an Authority Boundary
&lt;/h2&gt;

&lt;p&gt;I originally thought of the interface as the visual identity of the project: a mission-control orbit instead of another grid of cards and tables. While building the real workflow, it became something more useful.&lt;/p&gt;

&lt;p&gt;The TUI shows who currently has authority.&lt;/p&gt;

&lt;p&gt;SigNoz can provide evidence. The agent can propose a patch. Neither can create a pull request. When a proposed change passes policy, the mission pauses at HUMAN and shows the target repository. The operator must explicitly approve one draft-PR attempt.&lt;/p&gt;

&lt;p&gt;That approval is deliberately narrow. It does not authorize a merge or deployment. If GitHub rejects the request, Missio preserves the mission and returns control to the human instead of silently repeating a mutation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ending at Handoff, Not Pretending Recovery
&lt;/h2&gt;

&lt;p&gt;After approval, Missio creates a branch and draft pull request from the production revision identified by SigNoz. The evidence digest travels into the pull request, connecting the proposed change back to the incident that caused it.&lt;/p&gt;

&lt;p&gt;Missio then watches GitHub CI for the exact draft commit. When the checks pass, the final state is HANDOFF.&lt;/p&gt;

&lt;p&gt;That wording is intentional. Missio does not pretend that a green check means production has recovered. It tells the operator that an evidence-bound draft is ready for normal review, merge, and deployment. The pull request remains the place where engineers can inspect the change and make&lt;br&gt;
the final call.&lt;/p&gt;

&lt;p&gt;I considered extending the demo through automatic deployment, but it would have weakened the product's trust model. A hackathon animation should not manufacture authority that the real system&lt;br&gt;
does not have.&lt;/p&gt;

&lt;h2&gt;
  
  
  What SigNoz Made Possible
&lt;/h2&gt;

&lt;p&gt;Without SigNoz, this would be a code agent triggered by a Slack message. With SigNoz, the agent is grounded in an observed resource, time window, trace, code location, repository, and deployed revision.&lt;/p&gt;

&lt;p&gt;That context affects every later step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It decides whether a mission exists;&lt;/li&gt;
&lt;li&gt;It decides which source can be read;&lt;/li&gt;
&lt;li&gt;It constrains what the agent can change;&lt;/li&gt;
&lt;li&gt;It binds the draft pull request back to production evidence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The deepest lesson for me was that agent observability is not only about tracing what a model did. Observability can also control what the model is allowed to do next.&lt;/p&gt;

&lt;p&gt;Missio still leaves the final operational decision with a person. Its job is to turn a noisy incident into a reviewable, evidence-bound change without hiding the gaps along the way.&lt;/p&gt;

&lt;p&gt;You can explore &lt;a href="https://github.com/N-45div/Missio" rel="noopener noreferrer"&gt;Missio on GitHub&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you want to trace the pieces I built on, the most useful references were the SigNoz guides for&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://signoz.io/docs/userguide/query-builder-v5/" rel="noopener noreferrer"&gt;Query Builder&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://signoz.io/docs/ingestion/self-hosted/overview/" rel="noopener noreferrer"&gt;Self-hosted ingestion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://opentelemetry.io/docs/concepts/semantic-conventions/" rel="noopener noreferrer"&gt;OpenTelemetry semantic conventions&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>rust</category>
    </item>
    <item>
      <title>Building CanopySplit: A Deep Dive into Octant V2 Yield Donating Strategies</title>
      <dc:creator>N DIVIJ</dc:creator>
      <pubDate>Sun, 09 Nov 2025 22:02:34 +0000</pubDate>
      <link>https://dev.to/n45div/building-canopysplit-a-deep-dive-into-octant-v2-yield-donating-strategies-2oe4</link>
      <guid>https://dev.to/n45div/building-canopysplit-a-deep-dive-into-octant-v2-yield-donating-strategies-2oe4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CanopySplit&lt;/strong&gt; is a multi-layer DeFi protocol that transforms idle capital into climate impact. Users deposit WETH, earn yield through Aave v3, and automatically split 100% of profits among climate recipients—all while keeping their principal withdrawable at any time.&lt;/p&gt;

&lt;p&gt;This technical deep-dive covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Octant V2 Yield Donating Strategy architecture&lt;/li&gt;
&lt;li&gt;ERC-4626 vault integration with Aave v3&lt;/li&gt;
&lt;li&gt;Epoch-based donation splitting mechanics&lt;/li&gt;
&lt;li&gt;Custom Uniswap v4 hook for swap fee donations&lt;/li&gt;
&lt;li&gt;Production deployment challenges on Sepolia&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Live on Sepolia:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strategy: &lt;code&gt;0x0D1d8AE2dD0e4B06ca0Ef2949150eb021cAf6Ce9&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Splitter: &lt;code&gt;0xda5fA1c26Ec29497C2B103B385569286B30EC248&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Asset (WETH): &lt;code&gt;0xC558DBdd856501FCd9aaF1E62eae57A9F0629a3c&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────┐
│ User Wallet │
└──────┬──────┘
       │ deposit WETH
       ▼
┌──────────────────────────────┐
│ Aave4626YieldDonatingStrategy│ (ERC-4626 vault)
│ - Deposits to Aave v3        │
│ - Mints shares to users      │
│ - Reports profit → splitter  │
└──────────────┬───────────────┘
               │ mint donation shares
               ▼
┌──────────────────────────────┐
│ TriSplitDonationSplitter     │
│ - Holds strategy shares      │
│ - Epoch-based allocation     │
│ - 3 climate recipients       │
└──────┬───────────────────────┘
       │ distribute()
       ▼
┌─────────────────────────────────┐
│ Recipients (50% / 30% / 20%)    │
│ - Planters                      │
│ - MRV (Monitoring/Verification) │
│ - Maintenance                   │
└─────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 1: Octant V2 Yield Donating Strategy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Core Concept
&lt;/h3&gt;

&lt;p&gt;Octant V2 introduces &lt;strong&gt;Yield Donating Strategies&lt;/strong&gt; (YDS), which extend ERC-4626 with donation mechanics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface IYieldDonatingStrategy is IERC4626 {
    function report() external returns (uint256 profit, uint256 loss);
    function setDonationSplitter(address splitter) external;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key innovation:&lt;/strong&gt; When &lt;code&gt;report()&lt;/code&gt; is called:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calculate &lt;code&gt;profit = currentAssets - lastRecordedAssets&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If profit &amp;gt; 0: &lt;strong&gt;Mint shares to splitter&lt;/strong&gt; (not to users!)&lt;/li&gt;
&lt;li&gt;If loss &amp;gt; 0: &lt;strong&gt;Burn donation shares first&lt;/strong&gt;, protecting user capital&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users keep 100% of principal&lt;/li&gt;
&lt;li&gt;Donations absorb losses first&lt;/li&gt;
&lt;li&gt;No performance fees&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementation: Aave4626YieldDonatingStrategy
&lt;/h3&gt;

&lt;p&gt;We built an ERC-4626 wrapper around Aave v3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Aave4626YieldDonatingStrategy is YieldDonatingTokenizedStrategy {
    IERC4626 public immutable vault; // ATokenVault

    constructor(
        IERC20 asset_,
        IERC4626 vault_,
        string memory name_,
        address management_,
        address keeper_
    ) YieldDonatingTokenizedStrategy(asset_, name_, management_, keeper_) {
        vault = vault_;
        asset_.forceApprove(address(vault_), type(uint256).max);
    }

    function totalAssets() public view override returns (uint256) {
        uint256 shares = vault.balanceOf(address(this));
        return vault.convertToAssets(shares);
    }

    function _deployFunds(uint256 amount) internal override {
        vault.deposit(amount, address(this));
    }

    function _freeFunds(uint256 amount) internal override {
        vault.withdraw(amount, address(this), address(this));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why ERC-4626?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Composability:&lt;/strong&gt; Any ERC-4626 vault can plug in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-rebasing:&lt;/strong&gt; Fixed shares, yield in &lt;code&gt;convertToAssets()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety:&lt;/strong&gt; Vault enforces supply caps and liquidity checks&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The report() Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function report() external onlyKeepers returns (uint256 profit, uint256 loss) {
    uint256 currentAssets = totalAssets();
    uint256 lastAssets = lastRecordedAssets;

    if (currentAssets &amp;gt; lastAssets) {
        profit = currentAssets - lastAssets;

        // Mint shares to splitter (donation\!)
        uint256 sharesToMint = convertToShares(profit);
        _mint(donationSplitter, sharesToMint);

        emit Reported(profit, 0);
    } else if (currentAssets &amp;lt; lastAssets) {
        loss = lastAssets - currentAssets;

        // Burn donation shares first
        uint256 splitterShares = balanceOf(donationSplitter);
        uint256 splitterAssets = convertToAssets(splitterShares);

        if (splitterAssets &amp;gt;= loss) {
            uint256 sharesToBurn = convertToShares(loss);
            _burn(donationSplitter, sharesToBurn);
        } else {
            _burn(donationSplitter, splitterShares);
            // Remaining loss socialized across all shares
        }

        emit Reported(0, loss);
    }

    lastRecordedAssets = totalAssets();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Critical insight:&lt;/strong&gt; Minting shares (instead of transferring assets) means donations continue earning yield until distributed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Aave v3 Integration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ATokenVault: ERC-4626 Wrapper for Aave
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract ATokenVault is ERC4626, Ownable {
    IPool public immutable aavePool;
    IERC20 public immutable aToken;

    constructor(
        IERC20 asset_,
        IPoolAddressesProvider provider
    ) ERC4626(asset_) ERC20("Aave WETH Vault", "aWETHv") {
        aavePool = IPool(provider.getPool());
        aToken = IERC20(aavePool.getReserveData(address(asset_)).aTokenAddress);
    }

    function totalAssets() public view override returns (uint256) {
        return aToken.balanceOf(address(this)); // aTokens auto-accrue
    }

    function _deposit(address caller, address receiver, uint256 assets, uint256 shares) 
        internal override 
    {
        SafeERC20.safeTransferFrom(asset(), caller, address(this), assets);
        SafeERC20.forceApprove(asset(), address(aavePool), assets);

        aavePool.supply(address(asset()), assets, address(this), 0);

        _mint(receiver, shares);
        emit Deposit(caller, receiver, assets, shares);
    }

    function _withdraw(address caller, address receiver, address owner, uint256 assets, uint256 shares) 
        internal override 
    {
        if (caller \!= owner) {
            _spendAllowance(owner, caller, shares);
        }

        _burn(owner, shares);
        aavePool.withdraw(address(asset()), assets, receiver);

        emit Withdraw(caller, receiver, owner, assets, shares);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deployed on Sepolia:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vault: &lt;code&gt;0x6938238e57CBe1b4B51Eb3B51389cEf8d3a88521&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Asset: WETH (&lt;code&gt;0xC558DBdd856501FCd9aaF1E62eae57A9F0629a3c&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Aave Provider: &lt;code&gt;0x012bAC54348C0E635dCAc9D5FB99f06F24136C9A&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Part 3: TriSplit Donation Splitter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Epoch-Based Allocation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct Recipient {
    address addr;
    string role;
}

struct Policy {
    uint256 epoch;
    uint256[3] basisPoints; // [5000, 3000, 2000] = 50%, 30%, 20%
}

contract TriSplitDonationSplitter {
    Recipient[3] public recipients;
    Policy public currentPolicy;
    Policy public upcomingPolicy;
    IERC4626 public vault;

    function distribute() external {
        uint256 shares = vault.balanceOf(address(this));
        uint256 assets = vault.redeem(shares, address(this), address(this));

        uint256[3] memory amounts;
        for (uint256 i = 0; i &amp;lt; 3; i++) {
            amounts[i] = (assets * currentPolicy.basisPoints[i]) / 10_000;
            IERC20(vault.asset()).safeTransfer(recipients[i].addr, amounts[i]);
        }

        emit Distributed(currentPolicy.epoch, amounts, recipients);
    }

    function rollEpoch() external onlyOwner {
        currentPolicy = upcomingPolicy;
        upcomingPolicy.epoch++;
        emit EpochRolled(currentPolicy.epoch);
    }

    function setUpcomingPolicy(uint256[3] calldata bps) external onlyOwner {
        require(bps[0] + bps[1] + bps[2] == 10_000, "Must sum to 100%");
        upcomingPolicy.basisPoints = bps;
        emit UpcomingPolicySet(upcomingPolicy.epoch, bps);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why epochs?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recipients know their allocation in advance&lt;/li&gt;
&lt;li&gt;Owner can adjust future weights without disrupting current distributions&lt;/li&gt;
&lt;li&gt;Full on-chain transparency via events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Current allocation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Planters: 50% (&lt;code&gt;0xF9b2eFCAcc1B93c1bd7F898d0a8c4b34aBD78E53&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;MRV: 30% (&lt;code&gt;0x9261432cab3c0F83E86fa6e41E4a88dA06E7ecc6&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Maintenance: 20% (&lt;code&gt;0x89C13e8e5a81E775160322df9d7869893926A8Cc&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Part 4: Uniswap v4 Hook (Local PoC)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Extending Donations to Swap Fees
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract TriSplitDonationHook is BaseHook {
    struct HookConfig {
        address donationTarget;
        uint256 donationBps; // 100 = 1%
    }

    mapping(PoolId =&amp;gt; HookConfig) public configs;

    function afterSwap(
        address,
        PoolKey calldata key,
        IPoolManager.SwapParams calldata params,
        BalanceDelta delta,
        bytes calldata
    ) external override returns (bytes4, int128) {
        PoolId poolId = key.toId();
        HookConfig memory config = configs[poolId];

        if (config.donationTarget \!= address(0)) {
            Currency currency = params.zeroForOne ? key.currency0 : key.currency1;

            uint256 amountIn = params.zeroForOne 
                ? uint256(int256(-delta.amount0())) 
                : uint256(int256(-delta.amount1()));

            uint256 donation = (amountIn * config.donationBps) / 10_000;

            poolManager.take(currency, config.donationTarget, donation);

            emit DonationExecuted(poolId, donation, config.donationTarget);
        }

        return (this.afterSwap.selector, 0);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Testing on Anvil:&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;&lt;span class="c"&gt;# Deploy v4 infrastructure&lt;/span&gt;
forge script script/00_DeployV4.s.sol &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; http://127.0.0.1:8545

&lt;span class="c"&gt;# Deploy hook&lt;/span&gt;
forge script script/00_DeployHook.s.sol &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; http://127.0.0.1:8545

&lt;span class="c"&gt;# Initialize pool&lt;/span&gt;
forge script script/05_EnsureInitialized.s.sol &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; http://127.0.0.1:8545

&lt;span class="c"&gt;# Add liquidity&lt;/span&gt;
forge script script/02_AddLiquidity.s.sol &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; http://127.0.0.1:8545

&lt;span class="c"&gt;# Configure hook (1% donation)&lt;/span&gt;
forge script script/04_SetHookConfig.s.sol &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; http://127.0.0.1:8545

&lt;span class="c"&gt;# Execute swap (triggers donation\!)&lt;/span&gt;
forge script script/03_Swap.s.sol &lt;span class="nt"&gt;--broadcast&lt;/span&gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; http://127.0.0.1:8545
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 5: Frontend Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dynamic Asset Detection
&lt;/h3&gt;

&lt;p&gt;Instead of hardcoding USDC/WETH, we read the asset dynamically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useAssetInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strategyAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;assetAddress&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReadContract&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;strategyAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StrategyABI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;asset&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;symbol&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReadContract&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;assetAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ERC20ABI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;symbol&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReadContract&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;assetAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ERC20ABI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;decimals&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;assetAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Works with any ERC-20 asset&lt;/li&gt;
&lt;li&gt;No frontend redeployment needed&lt;/li&gt;
&lt;li&gt;Correct decimal formatting&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Role-Based Access Control
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AppPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAccount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;management&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReadContract&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ADDRS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sepolia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StrategyABI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;management&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isManagement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;management&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DepositForm&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WithdrawForm&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isManagement&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleReport&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Report&lt;/span&gt; &lt;span class="nx"&gt;Profit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;Loss&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Event Tracking
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useLifetimeDonations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;splitterAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContractEvent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;splitterAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SplitterABI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;eventName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Distributed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;fromBlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;totalDonated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;epoch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amounts&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;amounts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;totalDonated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;eventCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Challenge 1: Sepolia Gas Cap (16.7M)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Contract creation bytecode exceeded Sepolia's per-tx gas limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&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="c"&gt;# foundry.toml&lt;/span&gt;
&lt;span class="py"&gt;optimizer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;optimizer_runs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="py"&gt;via_ir&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="py"&gt;bytecode_hash&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"none"&lt;/span&gt;
&lt;span class="py"&gt;cbor_metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;forge clean &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; forge build
forge create YieldDonatingTokenizedStrategy &lt;span class="nt"&gt;--gas-limit&lt;/span&gt; 0xFD0000 &lt;span class="nt"&gt;--legacy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Challenge 2: WETH Pivot
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Aave v3 Sepolia USDC had supply cap issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Switched to WETH (18 decimals, no supply cap).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;USDC_UNDERLYING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0xC558DBdd856501FCd9aaF1E62eae57A9F0629a3c  &lt;span class="c"&gt;# WETH\!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Challenge 3: Permit2 Allowance
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Swaps reverted with &lt;code&gt;InsufficientAllowance&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Root cause:&lt;/strong&gt; Granted allowance to PoolManager, but Router calls &lt;code&gt;transferFrom()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&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;// Grant allowance to Router, not PoolManager
permit2.approve(address(token0), address(swapRouter), type(uint160).max, type(uint48).max);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Challenge 4: Token Decimals
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; USDC (6 decimals) vs WETH (18 decimals) mismatches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Created patching script 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;FakeUSDC fake = new FakeUSDC(); // decimals() = 6
vm.etch(token0Addr, address(fake).code);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Key Innovations
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Epoch-Based Splits:&lt;/strong&gt; Unlike single-recipient YDS, we route to 3 recipients with dynamic weights&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Adapter Support:&lt;/strong&gt; Idle, Aave v3, and ERC-4626 strategies all feed the same splitter&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Asset Detection:&lt;/strong&gt; Frontend works with any ERC-20 without hardcoding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks Integration:&lt;/strong&gt; Extended YDS concept to Uniswap v4 swap fees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loss Protection:&lt;/strong&gt; Donation shares burn first, protecting user capital&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;CanopySplit demonstrates how Octant V2's Yield Donating Strategies can be extended with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-protocol integrations&lt;/strong&gt; (Aave v3, Uniswap v4)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible donation mechanics&lt;/strong&gt; (epoch-based splits, loss protection)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production-ready UX&lt;/strong&gt; (dynamic asset detection, role-based access)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architecture is composable, transparent, and gas-efficient. All code is open-source and ready for judges to test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways for builders:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ERC-4626 is the perfect abstraction for yield strategies&lt;/li&gt;
&lt;li&gt;Epoch-based policies provide flexibility without disrupting current operations&lt;/li&gt;
&lt;li&gt;Dynamic asset detection makes frontends future-proof&lt;/li&gt;
&lt;li&gt;Testnet gas limits are real—optimize aggressively&lt;/li&gt;
&lt;li&gt;Always verify contract addresses exist on-chain before trusting deployment logs&lt;/li&gt;
&lt;/ol&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/N-45div/CanopySplit" rel="noopener noreferrer"&gt;https://github.com/N-45div/CanopySplit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sepolia Strategy:&lt;/strong&gt; &lt;code&gt;0x0D1d8AE2dD0e4B06ca0Ef2949150eb021cAf6Ce9&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sepolia Splitter:&lt;/strong&gt; &lt;code&gt;0xda5fA1c26Ec29497C2B103B385569286B30EC248&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Octant V2 Docs:&lt;/strong&gt; &lt;a href="https://docs.octant.app" rel="noopener noreferrer"&gt;docs.octant.app&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built with ❤️ for the Octant V2 hackathon. Questions? Reach out on Twitter &lt;a href="https://twitter.com/godlovesu_n" rel="noopener noreferrer"&gt;@godlovesu_n&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>ethereum</category>
      <category>web3</category>
    </item>
    <item>
      <title>Introducing "Resilient Response" - Empowering Disaster Relief and Management</title>
      <dc:creator>N DIVIJ</dc:creator>
      <pubDate>Wed, 16 Aug 2023 08:14:21 +0000</pubDate>
      <link>https://dev.to/n45div/introducing-resilient-response-empowering-disaster-relief-and-management-4o48</link>
      <guid>https://dev.to/n45div/introducing-resilient-response-empowering-disaster-relief-and-management-4o48</guid>
      <description>&lt;p&gt;Hey there, fellow developers and enthusiasts of this beautiful Dev Community&lt;/p&gt;

&lt;p&gt;I'm thrilled to introduce you to a project that's very close to my heart - &lt;strong&gt;"Resilient Response"&lt;/strong&gt;, an open-source application designed to revolutionize disaster relief and management efforts. 🚀&lt;/p&gt;

&lt;p&gt;🔗 Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://resilient-response.vercel.app/" rel="noopener noreferrer"&gt;https://resilient-response.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: 
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/N-45div" rel="noopener noreferrer"&gt;
        N-45div
      &lt;/a&gt; / &lt;a href="https://github.com/N-45div/Resilient-Response" rel="noopener noreferrer"&gt;
        Resilient-Response
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Our team is excited to announce the development of a cutting-edge web application both for mobile and desktop for the GDSC Solution Challenge 2023. With a mission to empower communities to withstand and recover from natural disasters, our app focuses on building resilience through innovative technology.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Resilient Response&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Resilient Response is a web application developed to foster connectivity and provide vital information during periods of crisis. This application was conceived as part of the 2023 Solution Challenge, which aligns with the overarching mission to address the United Nations' 17 Sustainable Development Goals by leveraging Google technology. The Resilient Response web app offers users the ability to register and access chat interfaces to stay informed about events occurring in their geographic area. In addition to real-time weather updates, the application also displays the locations of available shelters during times of emergency.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/N-45div/Resilient-Response/public/firebase.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FN-45div%2FResilient-Response%2Fpublic%2Ffirebase.png" width="175"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer" href="https://github.com/N-45div/Resilient-Response/public/tensorflow-ar21.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FN-45div%2FResilient-Response%2Fpublic%2Ftensorflow-ar21.png" width="175"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/N-45div/Resilient-Response/public/banner.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FN-45div%2FResilient-Response%2Fpublic%2Fbanner.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="https://www.youtube.com/watch?v=a0wbma13RkM" rel="nofollow noopener noreferrer"&gt;Our video presentation&lt;/a&gt;         &lt;a href="https://resilient-response.vercel.app/" rel="nofollow noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Our team is excited to announce the development of a cutting-edge web application both for mobile and desktop for the GDSC Solution Challenge 2023. With a mission to empower communities to withstand and recover from natural disasters, our app focuses on building resilience through innovative technology.We believe that by harnessing the&lt;/strong&gt;…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/N-45div/Resilient-Response" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Project Overview:&lt;/strong&gt;&lt;br&gt;
Disasters can strike unexpectedly and wreak havoc on communities. The key to minimizing their impact lies in effective coordination and rapid response. This is where Resilient Response comes in. It's a powerful application that combines cutting-edge technology with a user-friendly interface to streamline disaster relief operations.&lt;/p&gt;

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

&lt;p&gt;🗺️ &lt;strong&gt;Geolocation Integration:&lt;/strong&gt; With the integration of geolocation services, "Resilient Response" allows responders to locate the nearest available shelters relative to the user's current position. This functionality ensures efficient utilization of resources and quicker response times.&lt;/p&gt;

&lt;p&gt;📱 &lt;strong&gt;Mobile Compatibility:&lt;/strong&gt; In disaster scenarios, being able to access vital information on-the-go is crucial. Resilient Response is designed to work seamlessly on mobile devices, ensuring that responders can stay connected and informed, even in challenging environments.&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Open Source Collaboration:&lt;/strong&gt; Resilient Response is an open-source project, driven by collaboration and community involvement. Developers from all backgrounds can contribute to its growth, enhancing its capabilities and extending its reach.&lt;/p&gt;

&lt;p&gt;🎨 &lt;strong&gt;Design and User Experience:&lt;/strong&gt; Create intuitive interfaces that empower users to navigate through critical information effortlessly, even in stressful situations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Innovative Hand Gesture Recognition&lt;/strong&gt;: Utilizing TensorFlow, a powerful machine learning framework, we've developed an intelligent algorithm that can identify and interpret hand gestures even in low-light or dark environments. This allows survivors to communicate their presence and condition to rescuers without relying solely on verbal communication, which might not be feasible in noisy or chaotic situations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Hand Gestures?&lt;/strong&gt;&lt;br&gt;
Hand gestures are a universal form of communication that transcends language barriers. By incorporating this technology into "Resilient Response," we're enabling survivors, including those who might be injured or unable to speak, to make themselves understood and request assistance in a clear and intuitive way.&lt;/p&gt;

&lt;p&gt;🤖 &lt;strong&gt;Machine Learning Enthusiasts:&lt;/strong&gt; If you have expertise in machine learning, TensorFlow, or computer vision, your insights and skills can help us refine and enhance the hand gesture recognition algorithm.&lt;/p&gt;

&lt;p&gt;🧩 &lt;strong&gt;Testing and Feedback:&lt;/strong&gt; We're actively seeking individuals who can test the hand gesture recognition feature in various environments and provide valuable feedback for improvements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current Status and Future Vision of "Resilient Response"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current Status:&lt;/strong&gt;&lt;br&gt;
As of now, the "Resilient Response" project has reached a significant milestone. The core features that form the foundation of the application are in place and have been rigorously tested. Our team has poured countless hours into refining the user interface, optimizing performance, and ensuring the application's reliability, even in challenging scenarios.&lt;/p&gt;

&lt;p&gt;We've received valuable feedback from early users and collaborators, which has helped us fine-tune the user experience and identify areas for improvement. The project's &lt;a href="https://github.com/N-45div/Resilient-Response" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; has been bustling with activity, showcasing the collective efforts of developers who believe in the mission of enhancing disaster relief and management.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Looking Forward:&lt;/strong&gt;&lt;br&gt;
While we've come a long way, there's still much to be done. Our vision for the future of "Resilient Response" is bold and ambitious, and we're excited to share some of the key areas we're focusing on:&lt;/p&gt;

&lt;p&gt;🌐 &lt;strong&gt;Real-time Communication:&lt;/strong&gt; Resilient Response provides a platform for real-time communication between first responders, volunteers, and affected individuals. Whether it's sending alerts, sharing critical information, or coordinating rescue missions, the application ensures that everyone is on the same page.&lt;/p&gt;

&lt;p&gt;🌟 &lt;strong&gt;Enhanced User and Community Customization:&lt;/strong&gt; We're working on expanding the application's customization options, allowing different organizations and regions to tailor the platform to their specific needs. Flexibility is key, as each disaster scenario is unique.&lt;/p&gt;

&lt;p&gt;🗺️ &lt;strong&gt;Geospatial Mapping:&lt;/strong&gt; With integrated geospatial mapping, Resilient Response enables responders to visualize affected areas, assess damage, and plan their actions more efficiently. The map-based interface enhances decision-making and resource allocation.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Integration with Emergency Services:&lt;/strong&gt; Our goal is to forge partnerships with emergency services and governmental agencies to seamlessly integrate "Resilient Response" into their operations. This collaboration can lead to more coordinated and efficient disaster response efforts.&lt;/p&gt;

&lt;p&gt;🔮 &lt;strong&gt;Predictive Analytics:&lt;/strong&gt; Leveraging the power of data, we aim to develop predictive models that can forecast disaster trends and help communities prepare in advance. This proactive approach can save lives and resources.&lt;/p&gt;

&lt;p&gt;📚 &lt;strong&gt;Comprehensive Documentation:&lt;/strong&gt; As the project evolves, we understand the importance of clear and comprehensive documentation. We're investing in creating resources that make it easy for developers to understand and contribute to the project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Join Us in Shaping the Future:&lt;/strong&gt;&lt;br&gt;
I'm extending an open invitation to all of you to be a part of this exciting journey. Your skills, insights, and passion can contribute to the success of "Resilient Response" in ways that are beyond measure. Whether you're a seasoned developer, a creative designer, a data aficionado, or someone who simply cares deeply about making a positive impact, there's a role for you here.&lt;/p&gt;

&lt;p&gt;Let's continue collaborating on &lt;a href="https://github.com/N-45div/Resilient-Response" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, engaging in discussions, and pushing the boundaries of what technology can achieve in disaster relief and management. Together, we can make a tangible difference in the lives of people around the world.&lt;/p&gt;

&lt;p&gt;If you have any questions, ideas, or suggestions, please don't hesitate to reach out. Together, we can make a significant impact!&lt;/p&gt;

&lt;p&gt;Once again 🔗 Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website: &lt;a href="https://resilient-response.vercel.app/" rel="noopener noreferrer"&gt;https://resilient-response.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/N-45div/Resilient-Response" rel="noopener noreferrer"&gt;Resilient Response&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thank you for reading the post .. Have a great day ahead !
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>tensorflow</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
