<?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: Srashti</title>
    <description>The latest articles on DEV Community by Srashti (@srashti_a3904fc69ca75e7dd).</description>
    <link>https://dev.to/srashti_a3904fc69ca75e7dd</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%2F3977468%2Fd7e1e037-822c-4538-a8e5-3530eac94559.png</url>
      <title>DEV Community: Srashti</title>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/srashti_a3904fc69ca75e7dd"/>
    <language>en</language>
    <item>
      <title>I Took My DApp Off My Laptop. The Internet Did Not Care, But I Was Thrilled.</title>
      <dc:creator>Srashti</dc:creator>
      <pubDate>Fri, 03 Jul 2026 05:59:23 +0000</pubDate>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd/i-took-my-dapp-off-my-laptop-the-internet-did-not-care-but-i-was-thrilled-3lpp</link>
      <guid>https://dev.to/srashti_a3904fc69ca75e7dd/i-took-my-dapp-off-my-laptop-the-internet-did-not-care-but-i-was-thrilled-3lpp</guid>
      <description>&lt;p&gt;Here's an uncomfortable truth about local Hardhat networks.&lt;/p&gt;

&lt;p&gt;They feel real. They are not real.&lt;/p&gt;

&lt;p&gt;Everything I'd built so far — the contract, the tests, the MetaMask connection — ran on a network that exists only on my laptop, resets every time I restart it, and that literally nobody else on Earth can access.&lt;/p&gt;

&lt;p&gt;It was time to put this thing somewhere that actually counts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Local network vs public testnet — the difference that actually matters
&lt;/h2&gt;

&lt;p&gt;A local Hardhat network is basically a blockchain simulator. Fast, free, and fake. Perfect for testing. Useless for showing anyone else what you built.&lt;/p&gt;

&lt;p&gt;A public testnet — I'm using Sepolia, Ethereum's main test network — is a real, persistent, publicly accessible blockchain. The ETH on it has no real value, but everything else behaves exactly like mainnet. Real gas costs (in test ETH), real block times, real network conditions.&lt;/p&gt;

&lt;p&gt;If your contract works on Sepolia, you've actually proven something. If it only worked locally, you've proven... that it worked locally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting test ETH
&lt;/h2&gt;

&lt;p&gt;Before deploying anything, you need fake money to pay fake gas fees. Welcome to one of the stranger sentences in software development.&lt;/p&gt;

&lt;p&gt;Sepolia faucets give out free test ETH. I used one tied to my Alchemy account, pasted in my wallet address, and waited a couple minutes. Free money, zero value, completely necessary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Configuring Hardhat for Sepolia
&lt;/h2&gt;

&lt;p&gt;Back to &lt;code&gt;hardhat.config.js&lt;/code&gt; — except now it needs to know about a real network, not just the local simulator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nomicfoundation/hardhat-toolbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;solidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.8.20&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sepolia&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SEPOLIA_RPC_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things I had to get right here, and both involve secrets I should never, ever commit to GitHub.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SEPOLIA_RPC_URL&lt;/code&gt; — this is an endpoint that lets Hardhat actually talk to the Sepolia network. I got mine from Alchemy, free tier, no cost.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;PRIVATE_KEY&lt;/code&gt; — my wallet's private key, used to sign and pay for the deployment transaction. This one terrified me a little the first time. If this leaks, anyone can drain that wallet. I put both of these in a &lt;code&gt;.env&lt;/code&gt; file and added &lt;code&gt;.env&lt;/code&gt; to &lt;code&gt;.gitignore&lt;/code&gt; before I did anything else. Lesson learned before the mistake happened, for once.&lt;/p&gt;




&lt;h2&gt;
  
  
  Writing the deploy script
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hardhat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&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;CrowdFund&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContractFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CrowdFund&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crowdFund&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;CrowdFund&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crowdFund&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;waitForDeployment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CrowdFund deployed to:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crowdFund&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAddress&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exitCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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;Then actually run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat run scripts/deploy.js &lt;span class="nt"&gt;--network&lt;/span&gt; sepolia
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This took noticeably longer than deploying locally — because it's a real network with real block times, not an instant simulation. Watching the terminal just sit there for the first time was its own small lesson in patience.&lt;/p&gt;

&lt;p&gt;When it finally printed an address, that address was real. Anyone could look it up on Sepolia's block explorer and see my contract sitting there. That moment felt different from every local deploy before it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pointing the frontend at it
&lt;/h2&gt;

&lt;p&gt;Small but easy-to-forget step — the React app's &lt;code&gt;CONTRACT_ADDRESS&lt;/code&gt; had to change from the local Hardhat address to this new Sepolia one. And MetaMask had to actually be switched to the Sepolia network too, or none of this connects to anything.&lt;/p&gt;

&lt;p&gt;That mismatch — frontend pointed one place, wallet connected to another — is its own special category of confusing bug. Everything looks fine. Nothing works. No error tells you why.&lt;/p&gt;




&lt;h2&gt;
  
  
  The bug that actually got me: events not updating the frontend
&lt;/h2&gt;

&lt;p&gt;Here's the real problem I hit, and it's worth walking through honestly because the fix taught me something about how DApps are actually supposed to work.&lt;/p&gt;

&lt;p&gt;My UI showed a campaign's &lt;code&gt;amountRaised&lt;/code&gt; correctly right after I contributed — because I was calling the contract directly and re-fetching. But if someone &lt;em&gt;else&lt;/em&gt; contributed while I had the page open, my screen had no idea. It just sat there, stale, until I manually refreshed.&lt;/p&gt;

&lt;p&gt;The fix was adding events to the contract that I'd skipped back in the original version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event ContributionMade(uint256 campaignId, address contributor, uint256 amount);

function contribute(uint256 _campaignId) public payable {
    Campaign storage campaign = campaigns[_campaignId];

    require(block.timestamp &amp;lt; campaign.deadline, "Campaign has ended");
    require(msg.value &amp;gt; 0, "Contribution must be greater than zero");

    campaign.amountRaised += msg.value;
    contributions[_campaignId][msg.sender] += msg.value;

    emit ContributionMade(_campaignId, msg.sender, msg.value);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;emit&lt;/code&gt; broadcasts this event onto the blockchain every time someone contributes. Anything listening can pick it up in real time.&lt;/p&gt;

&lt;p&gt;Then on the frontend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ContributionMade&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="nx"&gt;campaignId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contributor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New contribution detected:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;campaignId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contributor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;refreshCampaignData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;campaignId&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;This is the piece I genuinely didn't understand until I needed it. Smart contracts don't push updates to a frontend automatically just because something changed. The frontend has to explicitly listen for events — and if you don't emit them in your contract, there's nothing to listen to in the first place.&lt;/p&gt;

&lt;p&gt;I had built a contract that worked perfectly and a frontend that had no way of knowing when things changed. Both pieces were "correct." Together, they were broken.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this bug actually matters beyond just fixing it
&lt;/h2&gt;

&lt;p&gt;This is the difference between writing a contract that works and building a DApp that feels alive.&lt;/p&gt;

&lt;p&gt;Without events, every user is stuck refreshing manually, never sure if what they're looking at is current. With events, the UI reacts the moment something happens on-chain — close to how a normal web app feels, except nothing here is coming from a server.&lt;/p&gt;

&lt;p&gt;It's a small addition to the Solidity code. It changes the entire feel of the product.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where things actually stand right now
&lt;/h2&gt;

&lt;p&gt;Honest status update, because that's the whole point of writing this in public:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contract is deployed on Sepolia, with a real address anyone can verify&lt;/li&gt;
&lt;li&gt;Frontend connects to it, creates campaigns, accepts contributions&lt;/li&gt;
&lt;li&gt;Events are now wired up, so the UI updates without manual refreshing&lt;/li&gt;
&lt;li&gt;Still rough around the edges — no proper campaign list view yet, styling is minimal, error handling is basic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't "the DApp is live and perfect." It's "the DApp is live, mostly works, and I know exactly what's left."&lt;/p&gt;

&lt;p&gt;That gap is smaller than it was at the start of this whole series. That's the actual win.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's left
&lt;/h2&gt;

&lt;p&gt;A real campaign listing page. Better error messages when a transaction fails instead of a raw MetaMask error. And eventually, a proper look at whether this is even ready to show people outside of me testing it alone.&lt;/p&gt;

&lt;p&gt;Getting something onto a public testnet didn't finish this project. It just moved the goalposts to something more honest.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Srashti Gupta, building in the Web3 space. I write about real builds, real bugs, and blockchain development from scratch. Let's connect on LinkedIn.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>tutorial</category>
      <category>devops</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>MetaMask, Wallets, and Why Ownership Actually Matters</title>
      <dc:creator>Srashti</dc:creator>
      <pubDate>Wed, 24 Jun 2026 05:10:33 +0000</pubDate>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd/metamask-wallets-and-why-ownership-actually-matters-5ejf</link>
      <guid>https://dev.to/srashti_a3904fc69ca75e7dd/metamask-wallets-and-why-ownership-actually-matters-5ejf</guid>
      <description>&lt;p&gt;Up until this post, my entire DApp lived in a terminal.&lt;/p&gt;

&lt;p&gt;Tests passed. Contract compiled. Everything technically worked. And none of it looked like anything a real human would ever want to use.&lt;/p&gt;

&lt;p&gt;Time to give it a face.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why MetaMask is the whole game here
&lt;/h2&gt;

&lt;p&gt;In a normal web app, you log in with an email and password. The server checks a database, decides who you are, and trusts that decision.&lt;/p&gt;

&lt;p&gt;There's no login here. There's no database deciding who you are.&lt;/p&gt;

&lt;p&gt;Instead, there's MetaMask — a wallet that holds your private key and lets you sign transactions. When you "connect" your wallet to a DApp, you're not logging into anything. You're just letting the website see your public address and asking your permission before any transaction goes out.&lt;/p&gt;

&lt;p&gt;Nobody can fake being you. Nobody can reset your password and lock you out. Your wallet &lt;em&gt;is&lt;/em&gt; your identity here, and only you control it.&lt;/p&gt;

&lt;p&gt;That's the part that actually matters. Not the UI. The ownership.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connecting the wallet
&lt;/h2&gt;

&lt;p&gt;In my React app, I'm using &lt;code&gt;ethers.js&lt;/code&gt; (Web3.js's sibling library — similar purpose, cleaner API) to talk to MetaMask.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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;account&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAccount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setProvider&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;connectWallet&lt;/span&gt;&lt;span class="p"&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="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MetaMask not found. Please install it.&lt;/span&gt;&lt;span class="dl"&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="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;browserProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BrowserProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&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;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;browserProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eth_requestAccounts&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="nf"&gt;setProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;browserProvider&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="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;&lt;/span&gt;&lt;span class="nx"&gt;div&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;account&lt;/span&gt; &lt;span class="p"&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="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Connected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)}...{&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&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;/p&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;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;connectWallet&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;Connect&lt;/span&gt; &lt;span class="nx"&gt;Wallet&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;/div&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;p&gt;&lt;code&gt;window.ethereum&lt;/code&gt; is the object MetaMask injects into every page you visit, automatically, the moment the extension is installed. If it's not there, MetaMask isn't installed — that's the first thing to check.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;eth_requestAccounts&lt;/code&gt; is what actually triggers that familiar MetaMask popup — "this site wants to connect to your wallet." The user has to approve it. Nothing happens silently.&lt;/p&gt;

&lt;p&gt;I'm slicing the address for display (&lt;code&gt;0x71C7...976F&lt;/code&gt; instead of the full 42 characters) because nobody wants to read a full wallet address on a button. Small detail, makes the UI feel less like a database dump.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting the contract talking to React
&lt;/h2&gt;

&lt;p&gt;Connecting a wallet is step one. Actually calling our contract's functions is step two.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CrowdFundABI&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./CrowdFund.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CONTRACT_ADDRESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0xYourDeployedContractAddress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;provider&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;signer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSigner&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Contract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CONTRACT_ADDRESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CrowdFundABI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signer&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;Remember that ABI file Hardhat generated back when we first compiled the contract? This is exactly where it gets used. The ABI tells &lt;code&gt;ethers.js&lt;/code&gt; what functions exist on our contract and what arguments they expect — without it, JavaScript has no idea our contract can even do anything.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;provider.getSigner()&lt;/code&gt; gets the actual connected account, the one capable of signing and sending transactions — not just reading data.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CONTRACT_ADDRESS&lt;/code&gt; is wherever our &lt;code&gt;CrowdFund&lt;/code&gt; contract actually got deployed. For now, that's a testnet address from Hardhat's local network or somewhere like Sepolia.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating a campaign from the UI
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createCampaign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;goalInEth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;durationInSeconds&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;contract&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;getContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;provider&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;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createCampaign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;goalInEth&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;durationInSeconds&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Campaign created!&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two steps, and the gap between them matters.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;contract.createCampaign(...)&lt;/code&gt; sends the transaction — MetaMask pops up, the user approves it, and it gets broadcast to the network. But sending a transaction and it actually being confirmed are different moments.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tx.wait()&lt;/code&gt; pauses until the transaction is actually mined into a block. Skip this step and your UI might say "Campaign created!" before the campaign genuinely exists on-chain — which is exactly the kind of bug that makes a DApp feel broken even when the contract is fine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contributing to a campaign
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;contributeToCampaign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;campaignId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amountInEth&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;contract&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;getContract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;provider&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;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;campaignId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amountInEth&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Contribution sent!&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same pattern as the test we wrote in the last post — &lt;code&gt;value&lt;/code&gt; in the call is what actually attaches real ETH to this transaction. The only difference now is a real human is clicking a real button, MetaMask is popping up with a real gas estimate, and real money is moving.&lt;/p&gt;

&lt;p&gt;This is the moment the whole project stops feeling like an exercise.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it actually feels like end to end
&lt;/h2&gt;

&lt;p&gt;Here's the full user journey, now that all of it connects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the app, click &lt;strong&gt;Connect Wallet&lt;/strong&gt; — MetaMask pops up, user approves&lt;/li&gt;
&lt;li&gt;Fill in a goal and duration, click &lt;strong&gt;Create Campaign&lt;/strong&gt; — MetaMask pops up again asking to confirm the transaction&lt;/li&gt;
&lt;li&gt;Wait a few seconds for confirmation, campaign appears&lt;/li&gt;
&lt;li&gt;Someone else opens the app, connects their own wallet, contributes ETH to that campaign — another MetaMask popup, another confirmation&lt;/li&gt;
&lt;li&gt;Refresh, and the campaign's raised amount has actually updated — read directly from the blockchain, not from any database&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No login. No backend tracking sessions. No "forgot password" flow. Just wallets, signatures, and a contract that doesn't care who you are beyond your address.&lt;/p&gt;




&lt;h2&gt;
  
  
  The bug that taught me something
&lt;/h2&gt;

&lt;p&gt;First time I tested this flow, I created a campaign, switched MetaMask to a different test account, and tried to contribute — except the contribution amount field still showed the &lt;em&gt;old&lt;/em&gt; account's input because I hadn't reset my component state on account change.&lt;/p&gt;

&lt;p&gt;MetaMask lets users switch accounts anytime, and your app needs to actually listen for that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accountsChanged&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="nx"&gt;accounts&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="nf"&gt;setAccount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this listener, your UI can silently show stale data tied to an account the user already switched away from. Small thing. Easy to miss. Definitely the kind of bug that erodes trust fast if a real user hits it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this matters beyond just "it works now"
&lt;/h2&gt;

&lt;p&gt;Stepping back for a second — what we just built is genuinely different from a normal web app's login flow.&lt;/p&gt;

&lt;p&gt;There's no "Srashti's account" sitting in a database somewhere that the platform can suspend, ban, or quietly modify. There's a wallet address, and whatever that address has done on-chain, visible to anyone, controlled by nobody but its owner.&lt;/p&gt;

&lt;p&gt;That's not a minor technical detail. That's the entire pitch of what we're building, finally made visible instead of theoretical.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Wallet connects. Campaigns get created. Contributions go through. The full loop actually works, end to end, with a real face on it.&lt;/p&gt;

&lt;p&gt;What's left is polish and reality — proper UI for displaying all active campaigns, progress bars toward each goal, and eventually pushing this from a local Hardhat network onto a real public testnet where anyone, anywhere, could actually try it.&lt;/p&gt;

&lt;p&gt;That's where this story is headed next.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Srashti Gupta, building in the Web3 space. I write about real builds, real bugs, and blockchain development from scratch. Let's connect on LinkedIn.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>javascript</category>
      <category>learning</category>
      <category>react</category>
    </item>
    <item>
      <title>From Remix to Hardhat: What Changes When You Go Pro</title>
      <dc:creator>Srashti</dc:creator>
      <pubDate>Fri, 19 Jun 2026 16:00:13 +0000</pubDate>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd/from-remix-to-hardhat-what-changes-when-you-go-pro-a06</link>
      <guid>https://dev.to/srashti_a3904fc69ca75e7dd/from-remix-to-hardhat-what-changes-when-you-go-pro-a06</guid>
      <description>&lt;p&gt;Remix spoiled me.&lt;/p&gt;

&lt;p&gt;Open browser. Write code. Compile. Deploy. No installation, no config files, no "why is this not working" at 11pm.&lt;/p&gt;

&lt;p&gt;Hardhat is the opposite of that. And honestly? That's the point.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why leave Remix at all
&lt;/h2&gt;

&lt;p&gt;Remix is great for learning. It is genuinely bad for building anything real.&lt;/p&gt;

&lt;p&gt;You can't version control it properly. You can't write proper automated tests. You can't integrate it with a frontend easily. Every real Web3 project — the ones actually shipping to mainnet — uses something like Hardhat or Foundry.&lt;/p&gt;

&lt;p&gt;So if the crowdfunding DApp is going to be a real thing and not just a browser tab, it has to move out of Remix.&lt;/p&gt;

&lt;p&gt;This is the "going pro" moment. It's also the first moment things stopped being smooth.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Node version trap nobody warns you about
&lt;/h2&gt;

&lt;p&gt;Here's the thing that cost me actual time before I even wrote a line of contract code.&lt;/p&gt;

&lt;p&gt;Hardhat needs a recent Node.js version. If you're running an older version — anything below Node 20 — newer Hardhat versions will either refuse to install properly or throw confusing errors that have absolutely nothing to do with the real problem.&lt;/p&gt;

&lt;p&gt;You'll see errors about modules, about syntax, about things that sound like your code is broken. It's not your code. It's your Node version.&lt;/p&gt;

&lt;p&gt;Check yours first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're below v20, update before doing anything else. I'm using &lt;code&gt;nvm&lt;/code&gt; (Node Version Manager) to handle this because switching Node versions between projects is just a fact of life in this ecosystem now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;20
nvm use 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save yourself the hour I lost. Check this before you touch Hardhat at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  Actually installing Hardhat
&lt;/h2&gt;

&lt;p&gt;Once Node is sorted, this part is simple.&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;mkdir &lt;/span&gt;crowdfund-dapp
&lt;span class="nb"&gt;cd &lt;/span&gt;crowdfund-dapp
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; hardhat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then initialize the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you options — pick the JavaScript project (TypeScript is great too, but one new thing at a time). It'll ask to install some dependencies. Say yes.&lt;/p&gt;




&lt;h2&gt;
  
  
  The config file that doesn't always behave
&lt;/h2&gt;

&lt;p&gt;Here's the second honest problem.&lt;/p&gt;

&lt;p&gt;Hardhat creates a &lt;code&gt;hardhat.config.js&lt;/code&gt; file automatically. Sometimes it generates clean. Sometimes — depending on the version, the Node setup, or honestly just bad luck — it doesn't set up correctly, and you get errors when you try to compile.&lt;/p&gt;

&lt;p&gt;If that happens to you, don't panic and don't assume you broke something fundamental. Just rewrite the config manually. Here's a clean baseline that works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nomicfoundation/hardhat-toolbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/** @type import('hardhat/config').HardhatUserConfig */&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;solidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.8.20&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./contracts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./cache&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;artifacts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./artifacts&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure the Solidity version here matches the &lt;code&gt;pragma solidity&lt;/code&gt; line in your contract. Mismatch between these two is one of the most common compile errors beginners hit, and the error message doesn't always make that obvious.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up the project structure
&lt;/h2&gt;

&lt;p&gt;Hardhat expects a specific folder structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crowdfund-dapp/
├── contracts/
│   └── CrowdFund.sol
├── test/
├── scripts/
└── hardhat.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drop the contract we wrote in the last post into &lt;code&gt;contracts/CrowdFund.sol&lt;/code&gt;. Exactly as written before — &lt;code&gt;createCampaign&lt;/code&gt;, &lt;code&gt;contribute&lt;/code&gt;, &lt;code&gt;withdraw&lt;/code&gt;, &lt;code&gt;refund&lt;/code&gt;, all of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Compiling for the first time
&lt;/h2&gt;

&lt;p&gt;This is the moment of truth.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx hardhat compile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything's set up right, you'll see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Compiled 1 Solidity file successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see red text instead — read the actual error, not just the first line. Most Hardhat compile errors are one of these three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Solidity version mismatch&lt;/strong&gt; — your &lt;code&gt;pragma&lt;/code&gt; line and your config don't agree&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing semicolon or bracket&lt;/strong&gt; — Solidity is strict, unlike JS where you can get away with a lot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node version issue&lt;/strong&gt; — back to the trap from earlier. If the error looks unrelated to your actual code, suspect this first&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What compiling actually does
&lt;/h2&gt;

&lt;p&gt;When this succeeds, Hardhat generates an &lt;code&gt;artifacts&lt;/code&gt; folder. Inside it sits the compiled bytecode and the ABI (Application Binary Interface) — basically the instruction manual that tells anything talking to this contract what functions exist and what they expect.&lt;/p&gt;

&lt;p&gt;This is the same ABI we'll eventually feed into Web3.js so the React frontend can actually talk to this contract. Compiling isn't just "checking for errors" — it's generating the exact files the rest of the DApp depends on.&lt;/p&gt;




&lt;h2&gt;
  
  
  The honest difference from Remix
&lt;/h2&gt;

&lt;p&gt;In Remix, compiling is instant and invisible. You don't think about Node versions, config files, or folder structures. It just runs.&lt;/p&gt;

&lt;p&gt;Hardhat makes you own all of that. More setup, more things that can break, more moments of staring at an error message that doesn't explain itself.&lt;/p&gt;

&lt;p&gt;But here's what you get in return — a project that's actually testable, versionable, and deployable to a real network in a real, repeatable way. Remix can't give you that.&lt;/p&gt;

&lt;p&gt;This is the trade every Solidity developer makes eventually. Comfort for control.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Contract is compiled. Files are generated. Project structure exists.&lt;/p&gt;

&lt;p&gt;Next up — actually writing tests. Because a contract that compiles isn't a contract that works. Those are two very different claims, and the gap between them is where bugs live.&lt;/p&gt;

&lt;p&gt;We're going to deliberately try to break this thing before anyone else gets the chance to.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Srashti Gupta, building in the Web3 space. I write about real builds, real setup headaches, and blockchain development from scratch. Let's connect on LinkedIn.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>programming</category>
      <category>javascript</category>
      <category>learning</category>
    </item>
    <item>
      <title>The Smart Contract That Handles Your Money. No Bank Needed</title>
      <dc:creator>Srashti</dc:creator>
      <pubDate>Tue, 16 Jun 2026 05:42:12 +0000</pubDate>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd/the-smart-contract-that-handles-your-money-no-bank-needed-1jkg</link>
      <guid>https://dev.to/srashti_a3904fc69ca75e7dd/the-smart-contract-that-handles-your-money-no-bank-needed-1jkg</guid>
      <description>&lt;h1&gt;
  
  
  The Smart Contract That Handles Your Money. No Bank Needed.
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;By Srashti Gupta |Blockchain Developer&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;This is the part where it gets real.&lt;/p&gt;

&lt;p&gt;Not "real" like inspirational. Real like — this contract will hold actual ETH. If I write the logic wrong, money doesn't go where it should. There's no "oops, let me push a fix." There's no customer support. There's no undo.&lt;/p&gt;

&lt;p&gt;So let's write it carefully. And let's actually understand every piece.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this contract needs to do
&lt;/h2&gt;

&lt;p&gt;Before touching Solidity, I always write the logic in plain English first. Sounds obvious. Saves hours.&lt;/p&gt;

&lt;p&gt;Here's what our crowdfunding contract needs to handle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A creator starts a campaign — sets a goal (in ETH) and a deadline&lt;/li&gt;
&lt;li&gt;Anyone can contribute ETH to a campaign&lt;/li&gt;
&lt;li&gt;If the goal is hit before the deadline → creator withdraws the funds&lt;/li&gt;
&lt;li&gt;If the deadline passes and the goal isn't hit → contributors get refunded&lt;/li&gt;
&lt;li&gt;Nobody can cheat any of this. The code enforces it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Five rules. One contract. Let's build it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up the contract
&lt;/h2&gt;



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

contract CrowdFund {

    struct Campaign {
        address creator;
        uint256 goal;
        uint256 deadline;
        uint256 amountRaised;
        bool withdrawn;
    }

    mapping(uint256 =&amp;gt; Campaign) public campaigns;
    mapping(uint256 =&amp;gt; mapping(address =&amp;gt; uint256)) public contributions;
    uint256 public campaignCount;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay, three things happening here worth pausing on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;Campaign&lt;/code&gt; struct&lt;/strong&gt; is how we store each campaign. Think of it as a row in a database — except this database is the blockchain and nobody owns it. &lt;code&gt;creator&lt;/code&gt; is the wallet address of whoever started the campaign. &lt;code&gt;goal&lt;/code&gt; and &lt;code&gt;deadline&lt;/code&gt; are set at creation. &lt;code&gt;amountRaised&lt;/code&gt; tracks total ETH contributed. &lt;code&gt;withdrawn&lt;/code&gt; is a boolean that makes sure the creator can only pull funds once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first mapping&lt;/strong&gt; — &lt;code&gt;mapping(uint256 =&amp;gt; Campaign)&lt;/code&gt; — connects a campaign ID (just a number) to its Campaign struct. Campaign 0, Campaign 1, Campaign 2. Simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second mapping&lt;/strong&gt; is the interesting one. &lt;code&gt;mapping(uint256 =&amp;gt; mapping(address =&amp;gt; uint256))&lt;/code&gt; — for each campaign, it tracks how much each wallet address contributed. This is what makes refunds possible. The contract remembers exactly who sent what.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;campaignCount&lt;/code&gt; starts at zero and increments every time a new campaign is created. That's our ID system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Creating a campaign
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createCampaign(uint256 _goal, uint256 _duration) public {
    require(_goal &amp;gt; 0, "Goal must be greater than zero");
    require(_duration &amp;gt; 0, "Duration must be greater than zero");

    campaigns[campaignCount] = Campaign({
        creator: msg.sender,
        goal: _goal,
        deadline: block.timestamp + _duration,
        amountRaised: 0,
        withdrawn: false
    });

    campaignCount++;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;msg.sender&lt;/code&gt; is one of my favourite things in Solidity. It's automatically the wallet address of whoever called this function. No login. No JWT token. No session. The blockchain already knows who you are.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;block.timestamp&lt;/code&gt; is the current time on the blockchain — in seconds. Adding &lt;code&gt;_duration&lt;/code&gt; (also in seconds) to it gives us the deadline.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;require&lt;/code&gt; statements are Solidity's way of saying "if this condition isn't true, stop everything and revert." Nobody can create a campaign with a zero goal or zero duration. The contract simply won't let it happen.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contributing to a campaign
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function contribute(uint256 _campaignId) public payable {
    Campaign storage campaign = campaigns[_campaignId];

    require(block.timestamp &amp;lt; campaign.deadline, "Campaign has ended");
    require(msg.value &amp;gt; 0, "Contribution must be greater than zero");

    campaign.amountRaised += msg.value;
    contributions[_campaignId][msg.sender] += msg.value;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things here that are unique to Solidity.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;payable&lt;/code&gt; — this keyword is what allows a function to receive ETH. Without it, any ETH sent to this function gets rejected. Most functions aren't payable. This one has to be.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;msg.value&lt;/code&gt; — the amount of ETH sent with this transaction, in wei (1 ETH = 10¹⁸ wei). When someone calls &lt;code&gt;contribute&lt;/code&gt;, the ETH they send travels with the function call and lands in the contract. The contract holds it. Not a bank. Not a server. The contract itself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Campaign storage campaign&lt;/code&gt; — the &lt;code&gt;storage&lt;/code&gt; keyword means we're pointing directly at the data on the blockchain, not making a copy of it. Changes we make here actually update the stored campaign. If we used &lt;code&gt;memory&lt;/code&gt; instead, changes would be lost. This is one of those Solidity details that bites beginners hard.&lt;/p&gt;




&lt;h2&gt;
  
  
  Withdrawing funds (if goal is hit)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function withdraw(uint256 _campaignId) public {
    Campaign storage campaign = campaigns[_campaignId];

    require(msg.sender == campaign.creator, "Only creator can withdraw");
    require(campaign.amountRaised &amp;gt;= campaign.goal, "Goal not reached");
    require(!campaign.withdrawn, "Already withdrawn");

    campaign.withdrawn = true;

    (bool success, ) = payable(campaign.creator).call{value: campaign.amountRaised}("");
    require(success, "Transfer failed");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three &lt;code&gt;require&lt;/code&gt; checks before a single wei moves. This is the security mindset Solidity forces on you.&lt;/p&gt;

&lt;p&gt;Only the creator can withdraw. The goal must be hit. And &lt;code&gt;withdrawn&lt;/code&gt; must be false — meaning this hasn't been called before. Setting &lt;code&gt;campaign.withdrawn = true&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; the transfer is intentional. It's called the checks-effects-interactions pattern, and it protects against a nasty attack called reentrancy where a malicious contract tries to drain funds by calling withdraw repeatedly before the first call finishes. Mark the state changed first. Then move the money.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.call{value: ...}("")&lt;/code&gt; syntax is the modern, recommended way to send ETH in Solidity. It returns a success boolean which we check. If the transfer fails for any reason, the whole transaction reverts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Refunding contributors (if goal isn't hit)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function refund(uint256 _campaignId) public {
    Campaign storage campaign = campaigns[_campaignId];

    require(block.timestamp &amp;gt;= campaign.deadline, "Campaign still active");
    require(campaign.amountRaised &amp;lt; campaign.goal, "Goal was reached, no refund");

    uint256 contributed = contributions[_campaignId][msg.sender];
    require(contributed &amp;gt; 0, "Nothing to refund");

    contributions[_campaignId][msg.sender] = 0;

    (bool success, ) = payable(msg.sender).call{value: contributed}("");
    require(success, "Refund failed");
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same pattern. Check everything first. Update state. Then move ETH.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;contributions[_campaignId][msg.sender] = 0&lt;/code&gt; before the transfer — again, reentrancy protection. If we checked the balance after the transfer, a malicious contract could call &lt;code&gt;refund&lt;/code&gt; repeatedly before the balance zeroes out and drain the whole thing.&lt;/p&gt;

&lt;p&gt;Each contributor calls &lt;code&gt;refund&lt;/code&gt; themselves. The contract doesn't loop through everyone and send it back automatically — that would be expensive in gas and risky. Instead, each person claims their own refund. Cleaner, safer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The full contract
&lt;/h2&gt;

&lt;p&gt;Here's everything together:&lt;br&gt;
&lt;/p&gt;

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

contract CrowdFund {

    struct Campaign {
        address creator;
        uint256 goal;
        uint256 deadline;
        uint256 amountRaised;
        bool withdrawn;
    }

    mapping(uint256 =&amp;gt; Campaign) public campaigns;
    mapping(uint256 =&amp;gt; mapping(address =&amp;gt; uint256)) public contributions;
    uint256 public campaignCount;

    function createCampaign(uint256 _goal, uint256 _duration) public {
        require(_goal &amp;gt; 0, "Goal must be greater than zero");
        require(_duration &amp;gt; 0, "Duration must be greater than zero");

        campaigns[campaignCount] = Campaign({
            creator: msg.sender,
            goal: _goal,
            deadline: block.timestamp + _duration,
            amountRaised: 0,
            withdrawn: false
        });

        campaignCount++;
    }

    function contribute(uint256 _campaignId) public payable {
        Campaign storage campaign = campaigns[_campaignId];

        require(block.timestamp &amp;lt; campaign.deadline, "Campaign has ended");
        require(msg.value &amp;gt; 0, "Contribution must be greater than zero");

        campaign.amountRaised += msg.value;
        contributions[_campaignId][msg.sender] += msg.value;
    }

    function withdraw(uint256 _campaignId) public {
        Campaign storage campaign = campaigns[_campaignId];

        require(msg.sender == campaign.creator, "Only creator can withdraw");
        require(campaign.amountRaised &amp;gt;= campaign.goal, "Goal not reached");
        require(!campaign.withdrawn, "Already withdrawn");

        campaign.withdrawn = true;

        (bool success, ) = payable(campaign.creator).call{value: campaign.amountRaised}("");
        require(success, "Transfer failed");
    }

    function refund(uint256 _campaignId) public {
        Campaign storage campaign = campaigns[_campaignId];

        require(block.timestamp &amp;gt;= campaign.deadline, "Campaign still active");
        require(campaign.amountRaised &amp;lt; campaign.goal, "Goal was reached, no refund");

        uint256 contributed = contributions[_campaignId][msg.sender];
        require(contributed &amp;gt; 0, "Nothing to refund");

        contributions[_campaignId][msg.sender] = 0;

        (bool success, ) = payable(msg.sender).call{value: contributed}("");
        require(success, "Refund failed");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under 70 lines. Handles real ETH. No database. No backend. No bank.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this contract can't do yet
&lt;/h2&gt;

&lt;p&gt;Being honest — this is a solid foundation, not a finished product.&lt;/p&gt;

&lt;p&gt;It doesn't have events yet — which means frontends can't listen for things like "campaign created" or "goal reached" in real time. That's next.&lt;/p&gt;

&lt;p&gt;It doesn't have an emergency pause. If a bug is found after deployment, this contract can't be stopped. That's what upgradeable contract patterns are for — a whole separate topic.&lt;/p&gt;

&lt;p&gt;And it hasn't been tested yet. Writing Solidity is one thing. Proving it does what you think it does is another. That's what Hardhat is for — and that's exactly what we're setting up next.&lt;/p&gt;




&lt;h2&gt;
  
  
  What just happened
&lt;/h2&gt;

&lt;p&gt;We wrote a contract that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accepts real ETH from real wallets&lt;/li&gt;
&lt;li&gt;Tracks who contributed what&lt;/li&gt;
&lt;li&gt;Releases funds only when conditions are met&lt;/li&gt;
&lt;li&gt;Refunds automatically when they're not&lt;/li&gt;
&lt;li&gt;Can't be tampered with by anyone — including me&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No Kickstarter. No bank. No middleman.&lt;/p&gt;

&lt;p&gt;Just code, sitting on a chain, doing exactly what it says.&lt;/p&gt;

&lt;p&gt;Next up — getting off Remix and setting up Hardhat. Because before this thing touches a testnet, we're going to break it on purpose and make sure it survives.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Srashti Gupta, building in the Web3 space. I write about real builds, real mistakes, and blockchain development from scratch. Let's connect on LinkedIn.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>web3</category>
      <category>learning</category>
    </item>
    <item>
      <title>I'm Building a Crowdfunding DApp. Here's Why Kickstarter Should Be Nervous</title>
      <dc:creator>Srashti</dc:creator>
      <pubDate>Mon, 15 Jun 2026 05:23:03 +0000</pubDate>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd/im-building-a-crowdfunding-dapp-heres-why-kickstarter-should-be-nervous-49c4</link>
      <guid>https://dev.to/srashti_a3904fc69ca75e7dd/im-building-a-crowdfunding-dapp-heres-why-kickstarter-should-be-nervous-49c4</guid>
      <description>&lt;p&gt;Okay Kickstarter isn't actually nervous. They don't know I exist.&lt;/p&gt;

&lt;p&gt;But hear me out.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem with crowdfunding platforms today
&lt;/h2&gt;

&lt;p&gt;Someone has a idea. A real one. They build a campaign, post it on Kickstarter or Indiegogo, and people start funding it. Thousands of people. Real money. Real trust.&lt;/p&gt;

&lt;p&gt;And then — Kickstarter takes 5%. Payment processors take another 3-5%. The creator waits weeks for the money to clear. The platform can suspend the campaign if they don't like something. The funds sit in an account controlled by a company you've never met.&lt;/p&gt;

&lt;p&gt;You trusted the idea. You're also trusting the platform. You don't get to choose.&lt;/p&gt;

&lt;p&gt;That bothered me. Because the platform isn't the product. The idea is the product. Why does the middleman get 10% and this much control?&lt;/p&gt;

&lt;p&gt;So I decided to build the version without the middleman.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'm building
&lt;/h2&gt;

&lt;p&gt;A decentralized crowdfunding DApp on Ethereum.&lt;/p&gt;

&lt;p&gt;Here's how it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anyone can create a campaign — set a goal (in ETH), set a deadline&lt;/li&gt;
&lt;li&gt;Anyone can fund a campaign — send ETH directly to the smart contract&lt;/li&gt;
&lt;li&gt;If the goal is hit before the deadline → funds release automatically to the creator&lt;/li&gt;
&lt;li&gt;If the goal isn't hit → every contributor gets their money back. Automatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No platform holding your funds. No approval process. No 5% cut disappearing into a company's revenue.&lt;/p&gt;

&lt;p&gt;The contract is the platform. The code is the rulebook. And anyone can read it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;p&gt;Here's what I'm working with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solidity&lt;/strong&gt; — for the smart contract. This is where the actual logic lives. Campaign creation, contribution tracking, goal checking, fund release — all of it written in Solidity and deployed on Ethereum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardhat&lt;/strong&gt; — for development and testing. Think of it as the environment where I write, compile, test, and deploy contracts without touching real ETH until I'm ready. If Remix was training wheels, Hardhat is the actual bike.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web3.js&lt;/strong&gt; — the bridge between the frontend and the blockchain. When someone clicks "Fund This Campaign" on the UI, Web3.js is what talks to their MetaMask wallet and sends the transaction to the contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React&lt;/strong&gt; — for the frontend. Campaign cards, contribution forms, progress bars, wallet connection. The part users actually see.&lt;/p&gt;

&lt;p&gt;Four technologies. One DApp. Starting from zero.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I'm documenting this as I build
&lt;/h2&gt;

&lt;p&gt;Here's the honest reason.&lt;/p&gt;

&lt;p&gt;I learn better when I write. Writing forces me to actually understand what I'm doing instead of copy-pasting from Stack Overflow and hoping it works. When I have to explain something, I find out fast whether I actually get it or just think I do.&lt;/p&gt;

&lt;p&gt;So this isn't a finished tutorial. I'm not going to pretend I built this perfectly and now I'm graciously sharing my wisdom.&lt;/p&gt;

&lt;p&gt;I'm building it right now. You're reading it as it happens. When something breaks — and things will break — I'll write about that too. When I don't understand something, I'll say so.&lt;/p&gt;

&lt;p&gt;That's the deal.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's coming next
&lt;/h2&gt;

&lt;p&gt;Here's what we're building, piece by piece:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next&lt;/strong&gt; — The smart contract. Writing the core Solidity code that handles campaigns, tracks contributions, and moves ETH. This is the heart of the whole thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After that&lt;/strong&gt; — Setting up Hardhat. Getting off Remix, writing real tests, deploying to a testnet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then&lt;/strong&gt; — Connecting MetaMask. Making the frontend actually talk to the contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finally&lt;/strong&gt; — Wrapping it all together. The full DApp, live on testnet, with everything working.&lt;/p&gt;

&lt;p&gt;One feature at a time. One post at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The part that genuinely excites me
&lt;/h2&gt;

&lt;p&gt;Here's what I keep coming back to.&lt;/p&gt;

&lt;p&gt;When this DApp is done, there's no server I'm running. No database I'm maintaining. No backend that goes down at 3am and pages me. The contract sits on Ethereum, and as long as Ethereum exists, the DApp exists.&lt;/p&gt;

&lt;p&gt;I write the code once. I deploy it. It runs.&lt;/p&gt;

&lt;p&gt;Forever.&lt;/p&gt;

&lt;p&gt;No AWS bill. No downtime. No "we're performing scheduled maintenance." Just a contract, on a chain, doing exactly what it says.&lt;/p&gt;

&lt;p&gt;That's the thing about building on blockchain that web dev can't give you. You don't just build a product. You build something that genuinely doesn't need you anymore once it's live.&lt;/p&gt;

&lt;p&gt;For a third-year CS student who can't afford servers — that's pretty great.&lt;/p&gt;




&lt;h2&gt;
  
  
  Come build this with me
&lt;/h2&gt;

&lt;p&gt;If you're learning Solidity, this is a good project to follow along with. Not too simple to be boring, not too complex to understand.&lt;/p&gt;

&lt;p&gt;If you're not learning Solidity — that's fine too. The concepts transfer. What does it mean to write logic that handles real money? What does it mean to build without a backend? These questions matter regardless of your stack.&lt;/p&gt;

&lt;p&gt;I'm building it in public. All of it — the working parts and the broken ones.&lt;/p&gt;

&lt;p&gt;Let's see what happens.  &lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Srashti Gupta,  building in the Web3 space. I write about blockchain, real builds, and things I'm figuring out as I go. Let's connect on LinkedIn.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title># Why I Chose Blockchain Over Normal Web Dev (And What I Gave Up)</title>
      <dc:creator>Srashti</dc:creator>
      <pubDate>Sun, 14 Jun 2026 05:16:40 +0000</pubDate>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd/-why-i-chose-blockchain-over-normal-web-dev-and-what-i-gave-up-2d79</link>
      <guid>https://dev.to/srashti_a3904fc69ca75e7dd/-why-i-chose-blockchain-over-normal-web-dev-and-what-i-gave-up-2d79</guid>
      <description>&lt;p&gt;Let me be honest with you about something.&lt;/p&gt;

&lt;p&gt;Choosing blockchain over regular web dev as a third-year CSE student is not the "safe" move. Nobody's recruiter is sliding into your DMs because you know Solidity. The placement cell doesn't have a checkbox for "deployed smart contracts on Ethereum."&lt;/p&gt;

&lt;p&gt;I chose it anyway. Here's the actual story.&lt;/p&gt;




&lt;h2&gt;
  
  
  The moment I looked at web dev and felt nothing
&lt;/h2&gt;

&lt;p&gt;First year. Everyone around me was learning React. HTML, CSS, JavaScript, then React, then Next.js, then whatever framework dropped last Tuesday.&lt;/p&gt;

&lt;p&gt;I tried. I built things. A portfolio site. A to-do app. The classic beginner projects that every tutorial sends you to build and every recruiter has already seen ten thousand times.&lt;/p&gt;

&lt;p&gt;And I kept thinking — &lt;em&gt;who else is doing exactly this right now?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answer was: a lot of people. A genuinely uncomfortable amount of people. All learning the same stack, building the same projects, competing for the same internships at the same companies.&lt;/p&gt;

&lt;p&gt;I didn't want to be in that queue. Not because I'm too good for it — I'm not. But because the queue was already so long, and I wasn't even sure I wanted to be at the front of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Then I found the question that changed everything
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;What if you could write code that nobody could tamper with?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've written about this before. But it's worth saying again because it's genuinely the reason I switched.&lt;/p&gt;

&lt;p&gt;Not the money. Not the hype. Not because "Web3 is the future" — I don't know if it is. Nobody does.&lt;/p&gt;

&lt;p&gt;It was that question. The idea that logic could sit on a chain, execute automatically, and be readable by anyone. No company behind it. No server you have to trust. No terms of service that can change overnight.&lt;/p&gt;

&lt;p&gt;Code as law. Not metaphorically. Literally.&lt;/p&gt;

&lt;p&gt;That idea grabbed me in a way that "build a full-stack CRUD app" never did.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I actually gave up
&lt;/h2&gt;

&lt;p&gt;I'm not going to pretend this was a cost-free decision. It wasn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The internship path is harder.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Web dev has a pipeline. Learn React → build projects → apply to startups → land a frontend internship. It's competitive but it's &lt;em&gt;mapped&lt;/em&gt;. The roadmap exists. Companies know what to look for. Candidates know what to build.&lt;/p&gt;

&lt;p&gt;Blockchain doesn't have that yet. Not in India. Not at the second-year level. There are companies building in Web3, but they're fewer, they're pickier, and they often want experience that takes longer to build.&lt;/p&gt;

&lt;p&gt;I knew this going in. I chose it anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The community is smaller.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stuck on a React bug? Stack Overflow has fourteen answers, three YouTube walkthroughs, and a Reddit thread from 2019 that somehow still applies.&lt;/p&gt;

&lt;p&gt;Stuck on a Solidity error? You're reading the docs, the GitHub issues, and occasionally a Discord server where someone might reply in four hours.&lt;/p&gt;

&lt;p&gt;I got used to figuring things out alone. Honestly? That's made me better at it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tutorials run out faster.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Web dev content is infinite. You could watch tutorials for a year and still have a queue.&lt;/p&gt;

&lt;p&gt;Solidity tutorials are good — Patrick Collins is genuinely excellent — but you hit the edge faster. At some point, you're reading Ethereum Improvement Proposals and audit reports to understand something. That's a different kind of learning.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I got instead
&lt;/h2&gt;

&lt;p&gt;Here's the thing nobody tells you about picking the less crowded path.&lt;/p&gt;

&lt;p&gt;When the field is smaller, &lt;em&gt;you stand out faster.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm a second-year student. I've deployed contracts on testnet, I'm building a crowdfunding DApp, and I write about it publicly. In web dev, that's table stakes. In blockchain, at my year, in my city? It's genuinely rare.&lt;/p&gt;

&lt;p&gt;I'm not saying I'm exceptional. I'm saying the bar to be visible is lower because fewer people are showing up consistently.&lt;/p&gt;

&lt;p&gt;And the problems are genuinely unsolved. In web dev, the wheel has been invented. You're optimizing it. In blockchain, people are still figuring out what the wheel should even be. Smart contract security, gas optimization, decentralized identity, cross-chain bridges — these aren't finished problems. They're open questions.&lt;/p&gt;

&lt;p&gt;I want to work on open questions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The honest version of "follow your passion"
&lt;/h2&gt;

&lt;p&gt;Everyone says follow your passion. Nobody says what happens when your passion is inconvenient.&lt;/p&gt;

&lt;p&gt;Blockchain is inconvenient. It's harder to learn, harder to get hired in, and harder to explain to relatives who want to know when you're getting a "real job."&lt;/p&gt;

&lt;p&gt;But every time I deploy a contract and watch it execute — no server, no company, no middleman — I feel something that I never felt building a to-do app.&lt;/p&gt;

&lt;p&gt;That feeling is worth the inconvenience.&lt;/p&gt;




&lt;h2&gt;
  
  
  If you're deciding right now
&lt;/h2&gt;

&lt;p&gt;If you're a CS student weighing this choice — I'm not telling you to pick blockchain. I'm telling you what I picked and why.&lt;/p&gt;

&lt;p&gt;Web dev is not lesser. It pays well, it has a clear path, and there's real craft in building great products. If React excites you the way Solidity excites me, do React. The passion matters more than the stack.&lt;/p&gt;

&lt;p&gt;But if you're in that queue and feeling nothing — maybe look at what's outside it.&lt;/p&gt;

&lt;p&gt;The crowded path is crowded for a reason. But it's not the only one.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Srashti Gupta, building in the Web3 space. I write about blockchain, real experiences, and things I'm figuring out in public. Let's connect on LinkedIn.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>developers</category>
    </item>
    <item>
      <title># What is a Smart Contract? I'll Explain It Like You're 15.</title>
      <dc:creator>Srashti</dc:creator>
      <pubDate>Fri, 12 Jun 2026 14:34:12 +0000</pubDate>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd/-what-is-a-smart-contract-ill-explain-it-like-youre-15-3c5</link>
      <guid>https://dev.to/srashti_a3904fc69ca75e7dd/-what-is-a-smart-contract-ill-explain-it-like-youre-15-3c5</guid>
      <description>&lt;p&gt;Okay real talk.&lt;/p&gt;

&lt;p&gt;When I first heard the term "smart contract" — I genuinely thought it was some kind of AI thing. Like a contract that reads itself and highlights the suspicious clauses your lawyer missed.&lt;/p&gt;

&lt;p&gt;It is not that.&lt;/p&gt;

&lt;p&gt;It's actually way cooler. And also kind of simpler. Let me explain it the way nobody explained it to me.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, forget everything you know about contracts
&lt;/h2&gt;

&lt;p&gt;A normal contract — the kind lawyers write — is a piece of paper (or a PDF nobody reads) that says:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"If X happens, then Y must do Z."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you buy a house, the contract says — seller hands over keys, buyer hands over money. Simple enough. But here's the thing: someone has to &lt;em&gt;enforce&lt;/em&gt; it. A bank. A lawyer. A court. Some middleman who takes a cut and also goes on holiday at the worst possible time.&lt;/p&gt;

&lt;p&gt;A smart contract does the same thing. &lt;em&gt;If X happens, then Y must do Z.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Except nobody enforces it. The code does.&lt;/p&gt;

&lt;p&gt;No middleman. No fees to a third party. No "we're processing your request, please allow 5-7 business days."&lt;/p&gt;

&lt;p&gt;Just: condition met → action executed. Automatically. On a blockchain. Forever.&lt;/p&gt;




&lt;h2&gt;
  
  
  The vending machine analogy (because it actually works)
&lt;/h2&gt;

&lt;p&gt;Think of a vending machine.&lt;/p&gt;

&lt;p&gt;You put in ₹20. You press B3. The chips drop. Done.&lt;/p&gt;

&lt;p&gt;The vending machine doesn't care who you are. It doesn't ask for your ID. It doesn't have a manager who needs to approve your chip request. You gave it the right input, it gave you the right output.&lt;/p&gt;

&lt;p&gt;Now imagine that vending machine is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Publicly visible&lt;/strong&gt; — anyone can see exactly how it works&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tamper-proof&lt;/strong&gt; — nobody can secretly reprogram it to steal your money&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Running forever&lt;/strong&gt; — it can't be "shut down" by any one person&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's a smart contract.&lt;/p&gt;




&lt;h2&gt;
  
  
  Okay but what does the code actually look like
&lt;/h2&gt;

&lt;p&gt;Here. I'll show you the simplest one that actually does something:&lt;br&gt;
&lt;/p&gt;

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

contract SimpleStorage {
    uint256 public myNumber;

    function store(uint256 _number) public {
        myNumber = _number;
    }

    function retrieve() public view returns (uint256) {
        return myNumber;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This contract does two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Store a number on the blockchain&lt;/li&gt;
&lt;li&gt;Let anyone retrieve that number&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. No database. No backend server. No hosting bill. The number lives on Ethereum — accessible to anyone, changeable only through the &lt;code&gt;store&lt;/code&gt; function, and permanent.&lt;/p&gt;

&lt;p&gt;"But Srashti, that's just a variable. My first Python script did that."&lt;/p&gt;

&lt;p&gt;Yes. But your Python script lived on your laptop. This lives on a global decentralized network that nobody controls. That's the difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why does this matter? (The part that actually hit me)
&lt;/h2&gt;

&lt;p&gt;Let me give you a real example.&lt;/p&gt;

&lt;p&gt;Imagine you and a friend make a bet. India wins the World Cup — you owe them ₹500. They win — they owe you ₹500.&lt;/p&gt;

&lt;p&gt;Normal situation: one of you is going to "forget." Or dispute the terms. Or just Venmo the wrong amount and pretend it's fine.&lt;/p&gt;

&lt;p&gt;Smart contract situation: you both lock ₹500 into a contract. The match result gets submitted (via something called an oracle — different topic). The contract automatically sends ₹1000 to the winner. No arguments. No awkward reminders. No "I'll pay you back next week."&lt;/p&gt;

&lt;p&gt;The code is the agreement. The code is the enforcement. They are the same thing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The part that sounds too good to be true
&lt;/h2&gt;

&lt;p&gt;"But what if the code has a bug?"&lt;/p&gt;

&lt;p&gt;Great question. This is actually the terrifying part.&lt;/p&gt;

&lt;p&gt;Once a smart contract is deployed on Ethereum, it's &lt;em&gt;immutable&lt;/em&gt; — meaning it can't be changed. If there's a bug, the bug is there forever. In 2016, a vulnerability in a smart contract called The DAO got exploited, and $60 million was drained.&lt;/p&gt;

&lt;p&gt;The code was the law. The code had a flaw. The law had a flaw.&lt;/p&gt;

&lt;p&gt;This is why security in Solidity is treated like a religion. You don't ship and hotfix. You audit, test, audit again, and then maybe think about deploying.&lt;/p&gt;

&lt;p&gt;It's also why I find it more interesting than regular web dev — the stakes are real. A badly written if-statement doesn't just break a feature. It can empty a wallet.&lt;/p&gt;




&lt;h2&gt;
  
  
  So where do smart contracts actually live
&lt;/h2&gt;

&lt;p&gt;On the Ethereum blockchain. Specifically, they live at an &lt;em&gt;address&lt;/em&gt; — just like your wallet has an address, contracts do too.&lt;/p&gt;

&lt;p&gt;Anyone can interact with a contract if they have its address and ABI (basically the contract's instruction manual — what functions exist and what they take as input).&lt;/p&gt;

&lt;p&gt;You don't need to trust the developer. You don't need to trust the platform. You just read the code and decide for yourself. Because the code is open, on-chain, and exactly what's running.&lt;/p&gt;

&lt;p&gt;That's the part that got me. Not the tech. The &lt;em&gt;philosophy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;What if the rules of a system were visible to everyone? What if "trust me" could be replaced by "read this"?&lt;/p&gt;

&lt;p&gt;That's what smart contracts are building toward.&lt;/p&gt;




&lt;h2&gt;
  
  
  The quick version if you zoned out
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A smart contract is code that runs on a blockchain&lt;/li&gt;
&lt;li&gt;It executes automatically when conditions are met — no human needed&lt;/li&gt;
&lt;li&gt;It's immutable once deployed — which makes security critical&lt;/li&gt;
&lt;li&gt;Anyone can read it — no black boxes, no "trust us"&lt;/li&gt;
&lt;li&gt;It's not AI. It's not magic. It's just logic that nobody can tamper with&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;From here, smart contracts get more interesting — events, mappings, modifiers, inheritance. The SimpleStorage above is barely scratching the surface.&lt;/p&gt;

&lt;p&gt;But the mental model? You now have it.&lt;/p&gt;

&lt;p&gt;Code is the contract. The blockchain is the judge. And nobody can bribe either of them.&lt;/p&gt;




&lt;p&gt;**&lt;/p&gt;

&lt;h3&gt;
  
  
  still learning still documenting
&lt;/h3&gt;

&lt;p&gt;**&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>tutorial</category>
      <category>web3</category>
    </item>
    <item>
      <title>I Learned Solidity From YouTube. Here's Exactly What Happened.</title>
      <dc:creator>Srashti</dc:creator>
      <pubDate>Wed, 10 Jun 2026 10:42:26 +0000</pubDate>
      <link>https://dev.to/srashti_a3904fc69ca75e7dd/i-learned-solidity-from-youtube-heres-exactly-what-happened-32gn</link>
      <guid>https://dev.to/srashti_a3904fc69ca75e7dd/i-learned-solidity-from-youtube-heres-exactly-what-happened-32gn</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa72kxuagiduseexxpucg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa72kxuagiduseexxpucg.png" alt=" " width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hey, I'm Srashti 👋 I'm a CSE student who is genuinely obsessed with blockchain and decentralized technology.&lt;/p&gt;

&lt;p&gt;While the standard path for many computer science students starts with building classic CRUD apps, I found myself pulled down a different rabbit hole entirely: deploying smart contracts on Remix and trying to understand the inner workings of Ethereum. I learned Solidity through YouTube, broke countless contracts, and slowly started to stitch the pieces together.&lt;/p&gt;

&lt;p&gt;Here is the honest breakdown of how I went from struggling with basic syntax to deploying decentralized applications—and how you can do it too.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Web3 Captured My Attention
&lt;/h2&gt;

&lt;p&gt;I wasn't chasing the crypto hype or looking at NFTs. What actually pulled me into the ecosystem was a foundational software engineering question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What if you could write code that nobody could tamper with?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No middlemen. No centralized servers controlled by a single entity. Just pure, immutable logic sitting on a blockchain, executing exactly as written forever. That concept shifted how I thought about programming. Eager to understand it, I went looking for high-quality educational resources and stumbled onto Patrick Collins' content on YouTube.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding the Right Mentor
&lt;/h3&gt;

&lt;p&gt;If you are a beginner trying to learn Solidity, Patrick Collins is highly recommended for a reason. His teaching style is clear, honest, and structurally sound. He explains the &lt;em&gt;why&lt;/em&gt; behind architectural patterns, not just the &lt;em&gt;how&lt;/em&gt;. For someone curious but completely new to web3 development, his deep dives made all the difference.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Remix? (And Why It’s the Perfect Launchpad)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.google.com/search?q=https://remix.ethereum.org/" rel="noopener noreferrer"&gt;Remix IDE&lt;/a&gt; is a browser-based development environment for writing, compiling, and deploying Solidity smart contracts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No Setup Required:&lt;/strong&gt; You don't have to fight your local environment, install dependencies, or configure path variables. You just open the tab and write code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heavy Lifting Included:&lt;/strong&gt; Remix handles the compiler, local deployment runtimes, and test networks out of the box, allowing you to focus purely on learning the language semantics.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Gap Between Theory and Code
&lt;/h2&gt;

&lt;p&gt;Understanding the high-level theory of a smart contract is straightforward. It functions essentially like a digital vending machine: you provide the correct input, and it guarantees a specific output without human intervention.&lt;/p&gt;

&lt;p&gt;But writing actual Solidity for the first time? That is where the friction starts. Take a look at this basic &lt;code&gt;SimpleStorage&lt;/code&gt; contract:&lt;br&gt;
&lt;/p&gt;

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

contract SimpleStorage {
    uint256 public myNumber;

    function store(uint256 _number) public {
        myNumber = _number;
    }

    function retrieve() public view returns (uint256) {
        return myNumber;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks simple on paper, but as a beginner, every line introduces a new mental hurdle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why does every file require an &lt;code&gt;SPDX-License-Identifier&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;What is the specific role of the &lt;code&gt;pragma solidity&lt;/code&gt; compiler flag?&lt;/li&gt;
&lt;li&gt;Why favor &lt;code&gt;uint256&lt;/code&gt; explicitly over standard integers?&lt;/li&gt;
&lt;li&gt;How do visibility modifiers like &lt;code&gt;public&lt;/code&gt; alter the state behavior and gas metrics?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bridging the gap between conceptual understanding and functional syntax is where most developers stall. My approach was iterative: I consistently rewatched technical breakdowns, analyzed compiler errors, and rewrote the same logic line-by-line until the underlying architecture made sense.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Moment It Clicked
&lt;/h3&gt;

&lt;p&gt;Everything changed when I deployed this contract to a local simulated network inside Remix. I executed the &lt;code&gt;store&lt;/code&gt; function, passed a parameter, signed the transaction, and called &lt;code&gt;retrieve&lt;/code&gt;. Seeing the state update seamlessly on a simulated blockchain layout made the theory real. There was no traditional database or centralized server backend—just the autonomous execution of the code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways Beyond the Syntax
&lt;/h2&gt;

&lt;p&gt;Moving past the basics taught me a few fundamental realities of blockchain development:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Solidity requires a completely different mental model.&lt;/strong&gt; While the syntax mirrors JavaScript, the execution environment does not. You are writing code for a decentralized state machine where every operations carries a gas cost and state modifications are permanent. Optimization is a necessity, not an afterthought.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remix is a testing ground, not a production suite.&lt;/strong&gt; Remix is incredible for rapid prototyping. However, scaling up means transitioning to professional frameworks like Hardhat or Foundry, and managing state interactions via developer tools like MetaMask.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging is the best teacher.&lt;/strong&gt; Deploys will fail, transactions will revert, and logic will break. Analyzing transaction logs and EVM execution errors teaches you more about the runtime environment than any passive tutorial ever could.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  My Current Stack and Next Steps
&lt;/h2&gt;

&lt;p&gt;Since writing that first &lt;code&gt;SimpleStorage&lt;/code&gt; contract, I've expanded my technical toolkit to include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced smart contract development with &lt;strong&gt;Solidity&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Testing, scripting, and local deployment pipelines using &lt;strong&gt;Hardhat&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Integrating decentralized backends with frontend applications using &lt;strong&gt;MetaMask&lt;/strong&gt; and &lt;strong&gt;Web3.js&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The learning curve in Web3 is continuous, and the best way to master it is to build actively. If you're looking to start, don't wait until you feel like you know everything. Open up an IDE, write a basic contract, analyze the edge cases, and start deploying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are you currently learning Solidity or building in Web3? Let's connect in the comments below—I'd love to hear about the projects you're working on or the resources that helped you clear the hurdle!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>ethereum</category>
      <category>web3</category>
      <category>smartcontract</category>
    </item>
  </channel>
</rss>
