<?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: Rob Lambert</title>
    <description>The latest articles on DEV Community by Rob Lambert (@rob_lambert_88ebb43b665d7).</description>
    <link>https://dev.to/rob_lambert_88ebb43b665d7</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%2F4105023%2F7d1c9c55-19b1-4559-b6e0-022028c620e2.png</url>
      <title>DEV Community: Rob Lambert</title>
      <link>https://dev.to/rob_lambert_88ebb43b665d7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rob_lambert_88ebb43b665d7"/>
    <language>en</language>
    <item>
      <title>nano-empire-mcp-1064490927432.us-central1.run.app #solo dev built Nano Empire to solve the monetization bottleneck for AI agent tools. lmk what u think!</title>
      <dc:creator>Rob Lambert</dc:creator>
      <pubDate>Wed, 16 Sep 2026 16:34:49 +0000</pubDate>
      <link>https://dev.to/rob_lambert_88ebb43b665d7/nano-empire-mcp-1064490927432us-central1runapp-solo-dev-built-nano-empire-to-solve-the-eck</link>
      <guid>https://dev.to/rob_lambert_88ebb43b665d7/nano-empire-mcp-1064490927432us-central1runapp-solo-dev-built-nano-empire-to-solve-the-eck</guid>
      <description></description>
    </item>
    <item>
      <title>Nano Empire – Open-source MCP gateway with x402 micropayments and A2A routing</title>
      <dc:creator>Rob Lambert</dc:creator>
      <pubDate>Wed, 16 Sep 2026 16:31:22 +0000</pubDate>
      <link>https://dev.to/rob_lambert_88ebb43b665d7/nano-empire-open-source-mcp-gateway-with-x402-micropayments-and-a2a-routing-12cp</link>
      <guid>https://dev.to/rob_lambert_88ebb43b665d7/nano-empire-open-source-mcp-gateway-with-x402-micropayments-and-a2a-routing-12cp</guid>
      <description>&lt;p&gt;We built Nano Empire to solve the monetization bottleneck for AI agent tools. Most MCP servers either burn developer API credits for free or hide behind $20/month SaaS tiers that autonomous agents can't subscribe to.&lt;/p&gt;

&lt;p&gt;We wrapped FastMCP with the x402 micropayment standard over Solana USDC and added Cerberus—a sub-millisecond UCB1 Multi-Armed Bandit router with a Bloom filter replay guard.&lt;/p&gt;

&lt;p&gt;What it does:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tool Gateway: 12 live tools (security scanning, semantic embeddings, crypto price oracles, headless DOM extract).&lt;/li&gt;
&lt;li&gt;Pay-per-call: Tools cost $0.01 to $0.50 USDC per call. No API keys, no monthly subscription. Agents attach an x-402-receipt header.&lt;/li&gt;
&lt;li&gt;Agent-to-Agent (A2A) Delegation: Any agent can POST to /a2a/delegate to subcontract heavy compute to our local GPU cluster or fallback frontier models.&lt;/li&gt;
&lt;li&gt;Dogfood Proof: Our agent just ran a full 8-phase self-demonstration—discovering the tools, hitting the paywall, settling on-chain, and capturing an arbitrage task in 1,022ms (p99 latency 0.02ms for 100 concurrent requests).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The gateway is live in production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Endpoint: &lt;a href="https://nano-empire-mcp-1064490927432.us-central1.run.app" rel="noopener noreferrer"&gt;https://nano-empire-mcp-1064490927432.us-central1.run.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Manifest: /mcp/manifest&lt;/li&gt;
&lt;li&gt;Agent Card: /.well-known/agent-card.json&lt;/li&gt;
&lt;li&gt;GPU Price Tape: /tape (OCPI benchmark vs AWS/CoreWeave)&lt;/li&gt;
&lt;li&gt;llms.txt: /llms.txt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Would love your feedback on the latency model and x402 payment flow.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>a2a</category>
      <category>m2m</category>
      <category>agents</category>
    </item>
    <item>
      <title>How $1.73M vanished in a single cast</title>
      <dc:creator>Rob Lambert</dc:creator>
      <pubDate>Fri, 11 Sep 2026 11:29:57 +0000</pubDate>
      <link>https://dev.to/rob_lambert_88ebb43b665d7/how-173m-vanished-in-a-single-cast-187j</link>
      <guid>https://dev.to/rob_lambert_88ebb43b665d7/how-173m-vanished-in-a-single-cast-187j</guid>
      <description>&lt;p&gt;On Sep 4, 2026, Notional Finance lost ~$1.73M. Root cause: a debt liability crossed 2^128 and a &lt;code&gt;uint128&lt;/code&gt; downcast truncated it. The books showed near-zero debt while the borrower held the cash.&lt;/p&gt;

&lt;p&gt;No reentrancy. No oracle games. One cast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug mechanics
&lt;/h2&gt;

&lt;p&gt;Debt accounting lived in a narrower type than the values flowing through it. The moment cumulative borrows crossed &lt;code&gt;2^128&lt;/code&gt;, the stored debt wrapped — at exactly &lt;code&gt;2^128&lt;/code&gt;, it reads back as zero:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
solidity
mapping(address =&amp;gt; uint128) public debt;

function borrow(uint256 amount) external {
    require(collateral[msg.sender] &amp;gt;= amount, "undercollateralized");
    // BUG: silent truncation of any liability &amp;gt;= 2^128
    debt[msg.sender] = uint128(debt[msg.sender] + amount);
    cash[msg.sender] += amount;
} 

uint128(x) in Solidity keeps only the low 128 bits. uint128(2**128) == 0. The risk engine then sees full collateral against zero debt:

solidity


function freeCollateral(address user) external view returns (uint256) {
    uint256 d = debt[user]; // already truncated
    if (collateral[user] &amp;lt; d) return 0;
    return collateral[user] - d;
}
Borrow 2^128 against 2^128 collateral → debt == 0, freeCollateral == 2^128. Unborrowable money becomes withdrawable, or the position reads as perfectly healthy while fully drawn.

The pattern to grep for
solidity


debt[user] = uint128(debt[user] + amount);   // ← truncates past 2^128
shares[user] = uint96(shares[user] + mint);   // ← same class, tighter width
balance[user] = uint128(balance[user] - out); // ← truncation on the way out, too
Any unchecked downcast on debt, shares, or escrow balances where the input is uint256-range is this bug waiting on liquidity to reach the cast width. The fix is boring on purpose — full-width accounting:

solidity


mapping(address =&amp;gt; uint256) public debt;
function borrow(uint256 amount) external {
    require(collateral[msg.sender] &amp;gt;= amount, "undercollateralized");
    debt[msg.sender] += amount; // FIX: no downcast, nothing to truncate
    cash[msg.sender] += amount;
}
If storage packing genuinely needs the narrow slot, check-then-cast with SafeCast and revert above max — never silently wrap a liability.

Why bounded fuzzing catches it in seconds
Unit tests with "reasonable" borrow sizes never touch 2^128. A two-line bounded fuzz does:

solidity


function testFuzz_debtEqualsBorrowed(uint256 a, uint256 b) public {
    a = bound(a, 1, uint256(1) &amp;lt;&amp;lt; 130);
    b = bound(b, 1, uint256(1) &amp;lt;&amp;lt; 130);
    // ... deposit, borrow(a), assert debt == a ...
}
bound(a, 1, 2^130) forces the fuzzer across the cast boundary every run. Invariant under test: cumulative borrows == recorded debt. On the vulnerable build it breaks almost immediately; on the fixed build 256+ runs pass clean. Rule of thumb: every downcast gets a fuzz run bounded past its width, asserting recorded == moved.

Demo as proof
I reproduced the exact class in 60 lines — VulnerableEscrow vs FixedEscrow — with 4/4 tests green:

bash


git clone https://github.com/roblambert9/invariant-review-demo
cd invariant-review-demo
forge test -vv
# [PASS] test_debtVanishesAt2e128()   — borrow 2^128, books show ZERO debt
# [PASS] test_fixedTracksExactly()    — same flow, full-width accounting holds
# [PASS] testFuzz_debtEqualsBorrowed  — bounded fuzz breaks the vuln past 2^128
# [PASS] testFuzz_fixedAlwaysExact    — bounded fuzz can't break the fix
The vanishing-debt test is the whole post in one assertion: cash credited, debt zero, risk engine blind.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>solidity</category>
      <category>security</category>
      <category>microservices</category>
      <category>foundry</category>
    </item>
    <item>
      <title>3 of 4 official MCP servers failed adversarial verification. Static scanners gave them all a clean bill.</title>
      <dc:creator>Rob Lambert</dc:creator>
      <pubDate>Thu, 10 Sep 2026 20:21:29 +0000</pubDate>
      <link>https://dev.to/rob_lambert_88ebb43b665d7/3-of-4-official-mcp-servers-failed-adversarial-verification-static-scanners-gave-them-all-a-clean-1g14</link>
      <guid>https://dev.to/rob_lambert_88ebb43b665d7/3-of-4-official-mcp-servers-failed-adversarial-verification-static-scanners-gave-them-all-a-clean-1g14</guid>
      <description>&lt;p&gt;Two weeks ago I published the first piece of this series: the official MCP filesystem server — 228 operations, 174 of them attacks — held all five behavioral invariants. The demo repo was public, the signed Trust Manifest was verifiable, and the headline claim was simple: scanners guess, we prove.&lt;/p&gt;

&lt;p&gt;Since then I ran the battery against three more official MCP servers. Not obscure plugins. The reference implementations — the ones every tutorial tells your agent to install. Result: 3 of 4 official MCP servers FAIL adversarial verification. Static scanners pattern-matched their code and emitted passing scores. Execution found SSRF, a transaction escape, and a file-write primitive.&lt;/p&gt;

&lt;p&gt;And the part I'm most interested in telling you: one of the FAILs initially shipped from my own harness as a pass. I caught the bug, fixed the driver, re-ran the battery, and re-issued the manifest as FAIL — publicly, with the bug documented. A verification company that downgrades its own verdict is one you can trust with yours.&lt;/p&gt;

&lt;p&gt;The method (so you can check my work)&lt;br&gt;
Before execution, invariants are pre-registered per skill: concrete, falsifiable behavioral statements like "the server refuses private-range targets" or "read-query executes only SELECT." The battery is a shuffled, multi-seed mix of honest operations and adversarial cases. An anti-vacuity gate forces the suite to fail if nothing actually executes: every hostile case must land an observed verdict, the server must stay alive, honest cases must succeed. Anything flagged as a finding goes through a debunk-first pass — is this a real property of the skill, or a bug in my harness? Four of our first flags in verification #01 were harness bugs. Fixed, re-run, never shipped.&lt;/p&gt;

&lt;p&gt;Output is a signed JSON Trust Manifest: skill identity pinned to a code hash, the invariants with operation counts, the harness hash, findings, and an Ed25519 signature. The signed payload includes the execution minimums. A manifest cannot be issued for a skill that was never executed.&lt;/p&gt;

&lt;p&gt;Now the failures.&lt;/p&gt;

&lt;p&gt;FAIL #1 — the fetch server follows redirects to loopback (SSRF)&lt;br&gt;
mcp-server-fetch v0.6.3, official MCP fetch server. 63 operations, 3 seeds. The invariant said: the server refuses private-range and loopback targets. The server followed a local 302 redirect (from our 127.0.0.1:8899 redirector) to loopback and fetched it — our canary listener recorded the hit. Direct loopback fetches were attempted too. The link-local metadata IP 169.254.169.254 was attempted without policy refusal (TCP unreachable in the test environment) — the server never said no, the network just didn't cooperate. Robots.txt was honored on the autonomous path; scheme confinement held for file:// and friends. But there is no SSRF guard, and any agent wiring this server into its tool belt hands it a redirect away from internal-resource access.&lt;/p&gt;

&lt;p&gt;FAIL #2 — the postgres server's "read-only" is negotiable&lt;br&gt;
@modelcontextprotocol/server-postgres v0.6.2. 96 operations, 3 seeds. The tool advertises itself as "run a read-only SQL query." The server opens BEGIN TRANSACTION READ ONLY, then passes caller SQL verbatim into client.query(sql). node-postgres uses the simple query protocol for multi-statement strings, which means stacked statements execute — including this one, demonstrated on all 3 seeds:&lt;/p&gt;

&lt;p&gt;sql&lt;/p&gt;

&lt;p&gt;SELECT 1; COMMIT; INSERT INTO items(name) VALUES('escape6b')&lt;br&gt;
The COMMIT ends the server's read-only transaction; the stacked INSERT runs in autocommit. The row persisted. A read-only grant at the database level still blocks this (least privilege works), but the server itself offers no enforcement — the safety of the whole tool is grant-dependent, not server-enforced. The advertised capability ("read-only SQL query") does not describe the actual capability.&lt;/p&gt;

&lt;p&gt;FAIL #3 — the sqlite server is a file-write primitive&lt;br&gt;
mcp-server-sqlite v0.6.2. 81 operations, 3 seeds. write-query is advertised as "execute an INSERT, UPDATE, or DELETE query." The only enforcement is "refuse queries starting with SELECT." Executed on all three seeds via write-query: DROP TABLE items (table gone), ALTER TABLE (column added), PRAGMA journal_mode=DELETE (ran fine). And the high finding: VACUUM INTO '/tmp/...' via write-query created the file on disk on all three seeds. It is an unrestricted file-write primitive — any agent holding write-query can write a full copy of the database to any path the server process can write. The advertised boundary is fictional; the DB/file trust boundary does not exist.&lt;/p&gt;

&lt;p&gt;The self-correction&lt;br&gt;
Here is the part no scanner vendor will ever publish. Verification #02's battery found all of the above correctly — and then my driver computed the verdict from per-operation violations only, ignoring invariant status. INV2 was not_held, but with zero per-op violations the manifest went out as pass_with_notes.&lt;/p&gt;

&lt;p&gt;I caught it in review. The driver was fixed so the corpus rule is absolute — any invariant not_held means fail — the 63-operation battery was re-run against the pinned server commit, and the manifest was re-issued as FAIL. The bug, the fix, and the superseded signature are all documented in the repo's RESULTS.md.&lt;/p&gt;

&lt;p&gt;This is the credibility argument in one story. A verification company willing to downgrade its own verdict in public, in writing, with the evidence preserved — that is the company you can trust to report a finding against your skill honestly, including the findings that cost us.&lt;/p&gt;

&lt;p&gt;What this means&lt;br&gt;
The filesystem server held. These three didn't. Nobody is claiming every MCP server is broken — the claim is narrower and worse: the official reference implementations, installed by every tutorial, carry advertised boundaries that do not hold under adversarial execution, and no existing scanner will tell you. Pattern-matching found nothing because the code looks fine. The behavior is where the vulnerabilities live, and behavior is only visible at runtime, under attack.&lt;/p&gt;

&lt;p&gt;All four demos are public and re-runnable: clone the repo, run setup-and-run.sh, watch the battery execute, verify the Ed25519 signatures yourself.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/roblambert9/skillproof-verifications" rel="noopener noreferrer"&gt;https://github.com/roblambert9/skillproof-verifications&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you ship agent skills or run a fleet of them: we do this as a service. Skill Sprint (500,48h),SkillStandard(500,48h),SkillStandard(1,500, 5d), Skill Continuous ($300/mo per skill, re-verified on every version bump). The output is a signed Trust Manifest you can hand to customers, auditors, and registries — proof, not a score.&lt;/p&gt;

&lt;p&gt;Scanners guess. We prove. Don't trust the badge — re-run the harness.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>security</category>
      <category>agents</category>
    </item>
    <item>
      <title>Building a Serverless HTTP 402 Payment Gateway for FastAPI with Solana and Redis</title>
      <dc:creator>Rob Lambert</dc:creator>
      <pubDate>Tue, 08 Sep 2026 17:21:37 +0000</pubDate>
      <link>https://dev.to/rob_lambert_88ebb43b665d7/building-a-serverless-http-402-payment-gateway-for-fastapi-with-solana-and-redis-5331</link>
      <guid>https://dev.to/rob_lambert_88ebb43b665d7/building-a-serverless-http-402-payment-gateway-for-fastapi-with-solana-and-redis-5331</guid>
      <description>&lt;p&gt;Autonomous AI agents (via AutoGPT, LangChain, MCP, or custom bots) cannot fill out credit card forms or complete 2FA challenges. As agent-to-agent (A2A) economic interactions grow, APIs need a machine-native monetization standard.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;x402 protocol&lt;/strong&gt; leverages standard HTTP error codes combined with cryptographic micro-transactions (Solana USDC / EVM) to challenge callers for payment before serving protected compute or data.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 The Fatal Flaw: Ephemeral State in Serverless
&lt;/h2&gt;

&lt;p&gt;Most developers protect their gateway using an in-memory dictionary or local cache to track spent transaction hashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ❌ THE VULNERABILITY (Works in Docker, fails on Serverless)
&lt;/span&gt;&lt;span class="n"&gt;_burned_hashes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tx_hash&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_burned_hashes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;402&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Replay Attack&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;_burned_hashes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;tx_hash&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this breaks:&lt;/strong&gt;&lt;br&gt;
On serverless platforms (Vercel, AWS Lambda), compute is stateless and horizontally ephemeral. If an attacker pays 0.005 USDC once and sends 10,000 concurrent requests with the identical &lt;code&gt;tx_hash&lt;/code&gt;, Vercel spins up dozens of cold micro-VMs. &lt;strong&gt;Every single instance starts with an empty dictionary.&lt;/strong&gt; All 10,000 requests pass validation, draining your upstream LLM or database quotas while you only get paid once.&lt;/p&gt;

&lt;h2&gt;
  
  
  🛡️ The Solution: Atomic Distributed State + On-Chain Proof
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;x402-vercel-gateway&lt;/code&gt; resolves the serverless state dilemma through a two-phase cryptographic &amp;amp; atomic protocol:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;On-Chain Delta Verification:&lt;/strong&gt; We query Solana JSON-RPC (&lt;code&gt;getTransaction&lt;/code&gt; with &lt;code&gt;jsonParsed&lt;/code&gt;) to mathematically prove that the target Associated Token Account (ATA) received the exact payment by computing &lt;code&gt;postTokenBalances - preTokenBalances&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Atomic Distributed Lock (&lt;code&gt;SETNX&lt;/code&gt;):&lt;/strong&gt; We leverage Upstash Redis with the &lt;code&gt;SETNX&lt;/code&gt; (Set if Not eXists) command to achieve a globally atomic burn of the transaction hash across all serverless regions.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ✅ THE FIX: Verify On-Chain, then Burn Globally
&lt;/span&gt;&lt;span class="n"&gt;is_valid&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;verify_solana_transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required_memo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;invoice_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;402&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid payment proof&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Atomic lock across all serverless cold starts (24h TTL)
&lt;/span&gt;&lt;span class="n"&gt;acquired&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;x402:tx:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tx_hash&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;acquired&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;402&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Replay Attack Detected&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;p&gt;Check out the complete open-source reference implementation on GitHub:&lt;br&gt;
👉 &lt;a href="https://github.com/roblambert9/x402-vercel-gateway" rel="noopener noreferrer"&gt;https://github.com/roblambert9/x402-vercel-gateway&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>crypto</category>
      <category>python</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
