<?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: Dhiraj Chaudhry</title>
    <description>The latest articles on DEV Community by Dhiraj Chaudhry (@dhirajlochib).</description>
    <link>https://dev.to/dhirajlochib</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%2F3915311%2F77fc62e3-5be4-4999-a2f5-f7f0f373a8fe.png</url>
      <title>DEV Community: Dhiraj Chaudhry</title>
      <link>https://dev.to/dhirajlochib</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dhirajlochib"/>
    <language>en</language>
    <item>
      <title>The Web3 Recovery Bug Wasn’t in the Smart Contract</title>
      <dc:creator>Dhiraj Chaudhry</dc:creator>
      <pubDate>Sat, 09 May 2026 06:41:29 +0000</pubDate>
      <link>https://dev.to/dhirajlochib/the-web3-recovery-bug-wasnt-in-the-smart-contract-4c2k</link>
      <guid>https://dev.to/dhirajlochib/the-web3-recovery-bug-wasnt-in-the-smart-contract-4c2k</guid>
      <description>&lt;p&gt;I recently worked on a crypto recovery flow where users could recover tokens sent to the wrong chain or unsupported wallet/account setup.&lt;/p&gt;

&lt;p&gt;At first, the flow looked simple:&lt;/p&gt;

&lt;p&gt;Detect the user wallet&lt;br&gt;
Select the chain&lt;br&gt;
Select the token&lt;br&gt;
Check token balance&lt;br&gt;
Enter recovery address&lt;br&gt;
Build recovery transaction&lt;br&gt;
Let the user sign and recover funds&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.upwork.com/freelancers/dhirajlochib" rel="noopener noreferrer"&gt;smart contract&lt;/a&gt; side was not the hardest part.&lt;/p&gt;

&lt;p&gt;The harder part was handling all the small assumptions around chains, token contracts, account factories, RPCs, and user expectations.&lt;/p&gt;

&lt;p&gt;The problem with “same address, same wallet”&lt;/p&gt;

&lt;p&gt;In EVM chains, the same address can exist across Ethereum, Polygon, BNB Chain, Arbitrum, Base, etc.&lt;/p&gt;

&lt;p&gt;But that does not mean the account behaves the same everywhere.&lt;/p&gt;

&lt;p&gt;One address can have:&lt;/p&gt;

&lt;p&gt;a smart account deployed on one chain&lt;br&gt;
no contract deployed on another chain&lt;br&gt;
a different factory on another chain&lt;br&gt;
token balance on one network&lt;br&gt;
zero balance on another&lt;br&gt;
different gas requirements&lt;br&gt;
different token contract mappings&lt;/p&gt;

&lt;p&gt;So this assumption is dangerous:&lt;/p&gt;

&lt;p&gt;`// bad assumption&lt;br&gt;
const account = await detectAccount(userAddress);&lt;/p&gt;

&lt;p&gt;A better approach is always chain-aware:&lt;/p&gt;

&lt;p&gt;const account = await detectAccount({&lt;br&gt;
  address: userAddress,&lt;br&gt;
  chainId: selectedChain.id,&lt;br&gt;
  rpcUrl: selectedChain.rpcUrl,&lt;br&gt;
});`&lt;/p&gt;

&lt;p&gt;It looks small, but this kind of difference matters a lot in Web3 apps.&lt;/p&gt;

&lt;p&gt;The bug: hardcoded chain detection&lt;/p&gt;

&lt;p&gt;One issue I ran into was factory detection being tied to the wrong chain.&lt;/p&gt;

&lt;p&gt;The app was checking an older smart account factory using Ethereum mainnet logic, then applying that result to other chains like BNB.&lt;/p&gt;

&lt;p&gt;That created a weird failure:&lt;/p&gt;

&lt;p&gt;Ethereum detection worked&lt;br&gt;
BNB recovery failed&lt;br&gt;
balance checks looked inconsistent&lt;br&gt;
the UI made it seem like the user had no recoverable funds&lt;/p&gt;

&lt;p&gt;The fix was tiny: use the selected chain’s RPC when detecting the factory.&lt;/p&gt;

&lt;p&gt;`const provider = new JsonRpcProvider(selectedChain.rpcUrl);&lt;/p&gt;

&lt;p&gt;const factory = await detectFactory({&lt;br&gt;
  provider,&lt;br&gt;
  accountAddress,&lt;br&gt;
  chainId: selectedChain.id,&lt;br&gt;
});`&lt;/p&gt;

&lt;p&gt;The lesson was simple:&lt;/p&gt;

&lt;p&gt;Do not let one default RPC quietly control multi-chain logic.&lt;/p&gt;

&lt;p&gt;Token symbols are not reliable&lt;/p&gt;

&lt;p&gt;Another problem was token mapping.&lt;/p&gt;

&lt;p&gt;Users often say:&lt;/p&gt;

&lt;p&gt;I sent USDT.&lt;/p&gt;

&lt;p&gt;But “USDT” does not always mean the same contract address on every chain.&lt;/p&gt;

&lt;p&gt;For example, USDT on Ethereum and USDT on BNB Chain are different token contracts.&lt;/p&gt;

&lt;p&gt;So this is not enough:&lt;/p&gt;

&lt;p&gt;`if (token.symbol === "USDT") {&lt;br&gt;
  // fetch balance&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;You need chain-specific token mapping:&lt;/p&gt;

&lt;p&gt;const TOKENS = {&lt;br&gt;
  ethereum: {&lt;br&gt;
    USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7",&lt;br&gt;
    USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",&lt;br&gt;
  },&lt;br&gt;
  bnb: {&lt;br&gt;
    USDT: "0x55d398326f99059fF775485246999027B3197955",&lt;br&gt;
    USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",&lt;br&gt;
  },&lt;br&gt;
};&lt;br&gt;
`&lt;br&gt;
The user sees a symbol.&lt;/p&gt;

&lt;p&gt;The app must care about the actual contract address.&lt;/p&gt;

&lt;p&gt;“$0 balance” is not always zero balance&lt;/p&gt;

&lt;p&gt;This was another annoying edge case.&lt;/p&gt;

&lt;p&gt;Sometimes the app showed $0 balance, but the real issue was not that the user had no funds.&lt;/p&gt;

&lt;p&gt;It could be:&lt;/p&gt;

&lt;p&gt;RPC rate limit&lt;br&gt;
wrong chain selected&lt;br&gt;
unsupported token contract&lt;br&gt;
old factory mismatch&lt;br&gt;
failed balance fetch&lt;br&gt;
bad provider response&lt;br&gt;
token list missing a contract address&lt;/p&gt;

&lt;p&gt;Showing all of these as “0 balance” is bad UX.&lt;/p&gt;

&lt;p&gt;A better pattern is to separate states clearly:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;type BalanceState =&lt;br&gt;
  | { status: "loading" }&lt;br&gt;
  | { status: "success"; balance: string }&lt;br&gt;
  | { status: "zero" }&lt;br&gt;
  | { status: "rpc_error"; message: string }&lt;br&gt;
  | { status: "unsupported_token" }&lt;br&gt;
  | { status: "unsupported_chain" };&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This makes debugging easier and prevents users from thinking their funds disappeared.&lt;/p&gt;

&lt;p&gt;Keep signing local&lt;/p&gt;

&lt;p&gt;For recovery flows, trust matters a lot.&lt;/p&gt;

&lt;p&gt;Users are already nervous because money is involved. The app should be very clear about what happens locally and what goes to the backend.&lt;/p&gt;

&lt;p&gt;My preferred approach:&lt;/p&gt;

&lt;p&gt;backend can provide config&lt;br&gt;
backend can provide supported chains/tokens&lt;br&gt;
backend can prepare payload details&lt;br&gt;
frontend handles wallet connection&lt;br&gt;
signing stays local in the browser&lt;br&gt;
sensitive signing material is never sent to the backend&lt;/p&gt;

&lt;p&gt;The product message should be simple:&lt;/p&gt;

&lt;p&gt;The app helps build the recovery transaction, but it does not custody your funds.&lt;/p&gt;

&lt;p&gt;That line matters.&lt;/p&gt;

&lt;p&gt;What I would do differently next time&lt;/p&gt;

&lt;p&gt;If I were building this again from scratch, I would spend more time on the configuration layer before touching the UI.&lt;/p&gt;

&lt;p&gt;Things I would define early:&lt;/p&gt;

&lt;p&gt;supported chains&lt;br&gt;
supported token contracts per chain&lt;br&gt;
old vs new factory logic&lt;br&gt;
RPC fallback strategy&lt;br&gt;
balance state handling&lt;br&gt;
account detection per chain&lt;br&gt;
recovery failure logs&lt;br&gt;
advanced debug info for support/admins&lt;/p&gt;

&lt;p&gt;Most Web3 bugs are not dramatic.&lt;/p&gt;

&lt;p&gt;A lot of them are boring configuration bugs with expensive consequences.&lt;/p&gt;

&lt;p&gt;Final takeaway&lt;/p&gt;

&lt;p&gt;The biggest lesson from this recovery flow was that a Web3 product can have clean contracts and still feel broken.&lt;/p&gt;

&lt;p&gt;The smart contract may be correct.&lt;/p&gt;

&lt;p&gt;But if the app:&lt;/p&gt;

&lt;p&gt;checks the wrong chain&lt;br&gt;
maps the wrong token&lt;br&gt;
hardcodes the wrong RPC&lt;br&gt;
hides real errors behind “$0 balance”&lt;br&gt;
assumes addresses behave the same everywhere&lt;/p&gt;

&lt;p&gt;then users will still think the product failed.&lt;/p&gt;

&lt;p&gt;For multi-chain Web3 apps, the infrastructure around the contract is just as important as the contract itself.&lt;/p&gt;

&lt;p&gt;Sometimes the bug is not in Solidity.&lt;/p&gt;

&lt;p&gt;Sometimes it is just one hardcoded chain check.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>nextjs</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How I Built a Production-Ready USDT Escrow System Using Solidity + Node.js</title>
      <dc:creator>Dhiraj Chaudhry</dc:creator>
      <pubDate>Wed, 06 May 2026 07:19:33 +0000</pubDate>
      <link>https://dev.to/dhirajlochib/how-i-built-a-production-ready-usdt-escrow-system-using-solidity-nodejs-2p3l</link>
      <guid>https://dev.to/dhirajlochib/how-i-built-a-production-ready-usdt-escrow-system-using-solidity-nodejs-2p3l</guid>
      <description>&lt;p&gt;Most blockchain payment tutorials focus only on sending transactions.&lt;/p&gt;

&lt;p&gt;Production systems are very different.&lt;/p&gt;

&lt;p&gt;A real crypto payment platform needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;escrow protection&lt;/li&gt;
&lt;li&gt;dispute handling&lt;/li&gt;
&lt;li&gt;transaction consistency&lt;/li&gt;
&lt;li&gt;wallet synchronization&lt;/li&gt;
&lt;li&gt;backend reliability&lt;/li&gt;
&lt;li&gt;scalable infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recently, I worked on building a USDT-based escrow payment platform designed for secure global crypto transfers with real-time transaction processing and dispute protection.&lt;/p&gt;

&lt;p&gt;My role:&lt;br&gt;
Lead Full-Stack &amp;amp; Smart Contract Developer&lt;/p&gt;

&lt;p&gt;Tech Stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solidity&lt;/li&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;web3.js&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;AWS&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was to create a secure payment infrastructure where users could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;send USDT globally&lt;/li&gt;
&lt;li&gt;protect payments using escrow&lt;/li&gt;
&lt;li&gt;handle disputes securely&lt;/li&gt;
&lt;li&gt;process transactions reliably in real time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest challenge wasn’t transferring crypto.&lt;/p&gt;

&lt;p&gt;It was building a system that could safely handle edge cases at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The platform was divided into two main layers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Contract Layer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;escrow custody&lt;/li&gt;
&lt;li&gt;release conditions&lt;/li&gt;
&lt;li&gt;dispute triggers&lt;/li&gt;
&lt;li&gt;transaction state management&lt;/li&gt;
&lt;li&gt;settlement execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Backend Infrastructure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Responsible for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;transaction monitoring&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;wallet management&lt;/li&gt;
&lt;li&gt;dispute workflows&lt;/li&gt;
&lt;li&gt;payment validation&lt;/li&gt;
&lt;li&gt;event synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation improved scalability while keeping payment settlement transparent on-chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Real Problem: Dispute Handling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most escrow systems work correctly on the happy path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Buyer pays&lt;/li&gt;
&lt;li&gt;Seller delivers&lt;/li&gt;
&lt;li&gt;Funds release&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The difficult part is handling failures and disputes.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;delayed blockchain confirmations&lt;/li&gt;
&lt;li&gt;duplicate webhook events&lt;/li&gt;
&lt;li&gt;wallet synchronization issues&lt;/li&gt;
&lt;li&gt;conflicting transaction states&lt;/li&gt;
&lt;li&gt;invalid delivery confirmations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To reduce inconsistent states, I implemented:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retry-safe transaction processing&lt;/li&gt;
&lt;li&gt;backend-side validation checkpoints&lt;/li&gt;
&lt;li&gt;time-locked escrow releases&lt;/li&gt;
&lt;li&gt;blockchain event synchronization&lt;/li&gt;
&lt;li&gt;transaction state verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This significantly improved reliability during concurrent transaction activity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend Scaling Challenges&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Crypto systems generate asynchronous events constantly.&lt;/p&gt;

&lt;p&gt;One transaction may trigger:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blockchain confirmations&lt;/li&gt;
&lt;li&gt;websocket updates&lt;/li&gt;
&lt;li&gt;webhook callbacks&lt;/li&gt;
&lt;li&gt;database writes&lt;/li&gt;
&lt;li&gt;user notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without proper synchronization, race conditions appear quickly.&lt;/p&gt;

&lt;p&gt;To improve consistency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis queues were introduced&lt;/li&gt;
&lt;li&gt;event processing was isolated&lt;/li&gt;
&lt;li&gt;retry-safe workers were implemented&lt;/li&gt;
&lt;li&gt;PostgreSQL transaction handling was optimized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reduced duplicate transaction states and improved processing reliability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Contract Security&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Security was one of the highest priorities during development.&lt;/p&gt;

&lt;p&gt;Important protections included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;reentrancy prevention&lt;/li&gt;
&lt;li&gt;restricted access control&lt;/li&gt;
&lt;li&gt;transaction validation checks&lt;/li&gt;
&lt;li&gt;safe withdrawal handling&lt;/li&gt;
&lt;li&gt;escrow timeout protection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every transaction state transition was validated before execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend &amp;amp; Infrastructure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The frontend was built using React and Next.js with a component-driven architecture focused on maintainability and performance.&lt;/p&gt;

&lt;p&gt;Frontend stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;shadcn/ui&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Infrastructure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nginx reverse proxy&lt;/li&gt;
&lt;li&gt;Ubuntu servers&lt;/li&gt;
&lt;li&gt;Dockerized deployment&lt;/li&gt;
&lt;li&gt;Redis queue handling&lt;/li&gt;
&lt;li&gt;PostgreSQL transactional storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Monitoring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sentry&lt;/li&gt;
&lt;li&gt;backend event logging&lt;/li&gt;
&lt;li&gt;transaction monitoring systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lessons Learned&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building blockchain systems is not just about deploying smart contracts.&lt;/p&gt;

&lt;p&gt;The hardest problems usually appear in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;backend synchronization&lt;/li&gt;
&lt;li&gt;infrastructure scaling&lt;/li&gt;
&lt;li&gt;transaction recovery&lt;/li&gt;
&lt;li&gt;event consistency&lt;/li&gt;
&lt;li&gt;production reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A secure Web3 platform requires strong coordination between smart contracts and backend infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building production-ready blockchain infrastructure requires much more than writing Solidity contracts.&lt;/p&gt;

&lt;p&gt;Real-world crypto systems need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scalable backend architecture&lt;/li&gt;
&lt;li&gt;secure transaction handling&lt;/li&gt;
&lt;li&gt;event consistency&lt;/li&gt;
&lt;li&gt;infrastructure reliability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Projects like this taught me that production engineering is where most blockchain complexity actually lives.&lt;/p&gt;

&lt;p&gt;If you're building infrastructure-heavy Web3 or backend systems, feel free to connect.&lt;/p&gt;

&lt;p&gt;GitHub:&lt;br&gt;
&lt;a href="https://github.com/dhirajlochib" rel="noopener noreferrer"&gt;https://github.com/dhirajlochib&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upwork:&lt;br&gt;
&lt;a href="https://www.upwork.com/freelancers/dhirajlochib" rel="noopener noreferrer"&gt;https://www.upwork.com/freelancers/dhirajlochib&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  blockchain #web3 #solidity #node
&lt;/h1&gt;

</description>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
