<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: crow</title>
    <description>The latest articles on Forem by crow (@crow004).</description>
    <link>https://forem.com/crow004</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3448700%2F75f05299-0268-41f8-8d1a-255feddb85e9.jpeg</url>
      <title>Forem: crow</title>
      <link>https://forem.com/crow004</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/crow004"/>
    <language>en</language>
    <item>
      <title>Why I Valued My Solo-Built Empire at $3.5M (And Why I’m Never Selling)</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Fri, 03 Apr 2026 11:44:56 +0000</pubDate>
      <link>https://forem.com/crow004/why-i-valued-my-solo-built-empire-at-35m-and-why-im-never-selling-pdp</link>
      <guid>https://forem.com/crow004/why-i-valued-my-solo-built-empire-at-35m-and-why-im-never-selling-pdp</guid>
      <description>&lt;p&gt;In the blockchain gaming industry, it's common to throw money around. Teams of 10 people often ask for millions of dollars based on "pretty pictures" and promises to build a metaverse in two years.&lt;/p&gt;

&lt;p&gt;I am building &lt;strong&gt;Musical Chairs&lt;/strong&gt; — a fully functional skill-to-earn ecosystem across 11 chains. When I tell people the project is valued at $3.5M (FDV), some see a price tag. I see a foundation. &lt;/p&gt;

&lt;p&gt;Let’s be clear: &lt;strong&gt;I am not selling this project. Not now, and not ever.&lt;/strong&gt; I’m building an empire, and today I’m putting on my venture analyst glasses to show why this valuation is actually a bargain for the 15% stake I’m making available to fuel our growth.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The "Solodev" Anomaly: A 5-Person Team in One Body
&lt;/h3&gt;

&lt;p&gt;Typically, a Seed-stage startup represents an execution risk. An investor pays for a team of 5-7 people to rent an office and deliver an MVP in six months.&lt;br&gt;
In my case, the MVP is already in production. I have personally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architected and written a resilient backend in Go.&lt;/li&gt;
&lt;li&gt;Deployed and tested smart contracts across 11 EVM networks (Base, Arbitrum, Ethereum, BSC, Polygon, etc.).&lt;/li&gt;
&lt;li&gt;Integrated complex hardware protection via Intel SGX to ensure 100% Provable Fairness.&lt;/li&gt;
&lt;li&gt;Set up the infrastructure: Nginx with Geo-IP, Umami analytics, and bridges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Financial Argument: Developing such a system with an outsourced agency would cost at least $200k–$300k. This technical risk has already been eliminated through my personal efforts ("Sweat Equity"). An investor isn't buying an idea; they are buying a battle-ready unit.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Technological Moat: SGX Protection
&lt;/h3&gt;

&lt;p&gt;Many Web3 games are simple forks or basic scripts. Musical Chairs is a hardware-sealed arena.&lt;br&gt;
We utilize Intel SGX enclaves. This means the winner-determination logic is hidden even from me as the server owner. This isn't just "plugging in a library" — it’s a sophisticated system architecture that will be extremely difficult and expensive for competitors to replicate. This is my "moat with crocodiles."&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Mass Onboarding: Killing the MetaMask Barrier
&lt;/h3&gt;

&lt;p&gt;The main problem with Web3 is the entry barrier. We’ve solved it radically by implementing an Account Abstraction (AA) stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Social Login (Web3Auth): Sign-in via Google, Apple, or X. No seed phrases for newcomers.&lt;/li&gt;
&lt;li&gt;Smart Accounts (SimpleSmartAccount): Every player automatically gets a secure ERC-4337 wallet.&lt;/li&gt;
&lt;li&gt;Infrastructure (Pimlico &amp;amp; permissionless.js): We use best-in-class bundlers and custom address prediction logic to handle cross-chain deployments seamlessly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our implementation even allows &lt;strong&gt;Direct Transfers&lt;/strong&gt; of ETH winnings to any EVM address directly from the game UI, effectively making the game a fully-functional wallet manager.&lt;/p&gt;

&lt;p&gt;Currently, we use a PULL model (player pays their own gas), but the architecture is ready to switch to Gasless via Paymasters in one click.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The Valuation Math: 3 Methods
&lt;/h3&gt;

&lt;p&gt;How do I justify that 15% of tokens are worth $525,000?&lt;/p&gt;

&lt;h4&gt;
  
  
  A. Comparable Company Method (Comps)
&lt;/h4&gt;

&lt;p&gt;Look at the market cap of GameFi projects on Arbitrum or Base. Even projects with average activity have an FDV in the $10M–$30M range. A $3.5M valuation gives an investor a 5x–10x growth potential just by reaching the market average.&lt;/p&gt;

&lt;h4&gt;
  
  
  B. Berkus Method (Scorecard)
&lt;/h4&gt;

&lt;p&gt;At early stages, points are awarded for core assets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sound Idea (11-chain game, zero inflation): $0.5M&lt;/li&gt;
&lt;li&gt;Working Product (Live on Mainnets, stable WebSocket): $1.0M&lt;/li&gt;
&lt;li&gt;Quality Management (Architecture ready for scaling): $1.0M&lt;/li&gt;
&lt;li&gt;Strategic Relationships (Mt Pelerin, Pimlico, Intel SGX): $1.0M
Total: $3.5M.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  C. Fuel for the Empire (The 15% Stake)
&lt;/h4&gt;

&lt;p&gt;I’m not looking for an "exit." I’m looking for a launchpad. The funding for this 15% stake has a surgical purpose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Engineering Power:&lt;/strong&gt; Hiring top-tier devs to work alongside me for the next 12+ months.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aggressive Marketing:&lt;/strong&gt; Global outreach to onboard the first 100k users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Economic Stability:&lt;/strong&gt; Allocating &lt;strong&gt;$200k directly into the liquidity pool&lt;/strong&gt; of our future token to ensure price stability from day one.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The Vision: From Solo Empire to DAO
&lt;/h3&gt;

&lt;p&gt;Developers often undervalue their work because they see the "sausage being made." But to the outside world, a hardware-protected, multi-chain platform built by one person is an anomaly.&lt;/p&gt;

&lt;p&gt;I’m not selling an investor my exhaustion; I’m offering a seat at the table of a project designed to outlive its creator. My end goal is to transition Musical Chairs into a &lt;strong&gt;DAO (Decentralized Autonomous Organization)&lt;/strong&gt;, where the ownership and governance belong to the community.&lt;/p&gt;

&lt;p&gt;I’m building a legacy. If you want to buy a commodity, look elsewhere. If you want to back an empire, welcome to the Arena.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Follow the project at &lt;a href="https://muschairs.com" rel="noopener noreferrer"&gt;muschairs.com&lt;/a&gt; or join us on Twitter &lt;a href="https://twitter.com/muschairs" rel="noopener noreferrer"&gt;@muschairs&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>solodev</category>
      <category>accountabstraction</category>
    </item>
    <item>
      <title>Building a Provably Fair Real-Time Game: The Limits of Trust and Intel SGX</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Sat, 07 Mar 2026 15:33:01 +0000</pubDate>
      <link>https://forem.com/crow004/building-a-provably-fair-real-time-game-the-limits-of-trust-and-intel-sgx-3e8g</link>
      <guid>https://forem.com/crow004/building-a-provably-fair-real-time-game-the-limits-of-trust-and-intel-sgx-3e8g</guid>
      <description>&lt;h2&gt;
  
  
  Description: "A deep dive into using Intel SGX to create a verifiably fair online game, and an honest look at the one attack vector that even a hardware enclave can't stop."
&lt;/h2&gt;

&lt;p&gt;As a solo dev building a real-time, skill-to-earn crypto game, my number one obsession is fairness. If players are putting real money on the line, they need to trust that the game isn't rigged. The problem? Every traditional game server is a "black box".&lt;/p&gt;

&lt;p&gt;Even when I opened the source code of my smart contracts, how can players trust that my backend server—the one receiving their clicks and sending results to the blockchain—isn't manipulating the data? What if I, the admin, decide to give my friend a 10-second head start by tweaking a timestamp?&lt;/p&gt;

&lt;p&gt;This is the trust paradox of centralized servers in a decentralized world. My solution was to go nuclear: I built my game's core logic inside an &lt;strong&gt;Intel SGX enclave&lt;/strong&gt;. It was a journey of sleepless nights, but the result is a system that is provably fair against almost every conceivable threat.&lt;/p&gt;

&lt;p&gt;Here's how it works, and an honest look at the one "final boss" attack vector that remains.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution: A Trusted Judge in a Hardware Vault
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxjj28lclaah4k6ci6n6.jpg" 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%2Fkxjj28lclaah4k6ci6n6.jpg" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
The core idea is simple: the part of the code that decides who wins and who loses doesn't run on my main backend. It runs inside an &lt;strong&gt;Intel SGX Enclave&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of an enclave as a locked, armored vault inside the server's CPU.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Isolation:&lt;/strong&gt; The code and memory inside the enclave are encrypted and isolated from the rest of the server. Even if someone gains root access to my server, they cannot see or modify what's happening inside the enclave.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Attestation:&lt;/strong&gt; The CPU itself can produce a signed "report" that cryptographically proves &lt;em&gt;exactly&lt;/em&gt; what code is running inside that vault.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means the enclave acts as a &lt;strong&gt;Trusted Judge&lt;/strong&gt;. My backend's only job is to shuttle data to and from this judge. It can't influence the verdict.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Proving the Judge is Honest (Remote Attestation)
&lt;/h3&gt;

&lt;p&gt;This is where the magic happens. How can a player trust the judge? They can ask for its credentials.&lt;/p&gt;

&lt;p&gt;When a player clicks "Verify Enclave" on my site, this happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The frontend sends a random, unique string (a &lt;code&gt;nonce&lt;/code&gt;) to the backend.&lt;/li&gt;
&lt;li&gt; The backend passes this &lt;code&gt;nonce&lt;/code&gt; to the enclave.&lt;/li&gt;
&lt;li&gt; The enclave asks the Intel CPU to generate a &lt;strong&gt;Remote Attestation Quote&lt;/strong&gt;. This quote is a data blob containing cryptographic measurements of the enclave's code (a hash called &lt;code&gt;MRENCLAVE&lt;/code&gt;) and the &lt;code&gt;nonce&lt;/code&gt; we sent. This entire blob is signed by the CPU's private key, which is fused into the silicon at the factory.&lt;/li&gt;
&lt;li&gt; This signed report is sent back to the player's browser.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The player's browser can now verify the Intel signature and see the &lt;code&gt;MRENCLAVE&lt;/code&gt; hash. They can then go to my open-source repository, build the enclave code themselves, and verify that the hash matches.&lt;/p&gt;

&lt;p&gt;This proves that the code running on my server is the exact same open-source code available to the public. &lt;strong&gt;I, as the admin, cannot secretly change the rules.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Blind Justice (Encrypted Clicks)
&lt;/h3&gt;

&lt;p&gt;We've implemented an additional layer of fairness: &lt;strong&gt;End-to-End Encryption&lt;/strong&gt; for player actions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The frontend fetches the Enclave's &lt;strong&gt;Public Encryption Key&lt;/strong&gt; (which is bound to the hardware attestation).&lt;/li&gt;
&lt;li&gt; When a player clicks, their action (including their address) is encrypted &lt;em&gt;on the client side&lt;/em&gt; using this key.&lt;/li&gt;
&lt;li&gt; The backend receives an encrypted blob. It has no idea &lt;em&gt;who&lt;/em&gt; clicked, only &lt;em&gt;that&lt;/em&gt; a click occurred.&lt;/li&gt;
&lt;li&gt; The backend timestamps the blob and passes it to the Enclave.&lt;/li&gt;
&lt;li&gt; Only inside the secure Enclave is the click decrypted and processed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This prevents the backend (or a malicious admin) from selectively censoring or delaying clicks from specific players (e.g., "let my friend win"). The backend is blind until the Enclave reveals the winner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Proving the Verdict is Authentic (Signed Results)
&lt;/h3&gt;

&lt;p&gt;Okay, so the judge is honest. But what if the backend just ignores the judge's verdict and writes a different winner to the database?&lt;/p&gt;

&lt;p&gt;To solve this, we added another layer. The enclave doesn't just &lt;em&gt;return&lt;/em&gt; a result; it &lt;strong&gt;cryptographically signs&lt;/strong&gt; it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; On startup, the enclave generates a temporary, session-specific key pair (private/public).&lt;/li&gt;
&lt;li&gt; When it generates an attestation report, it includes a hash of its new public key in the report data. This links the hardware-verified enclave to this specific public key.&lt;/li&gt;
&lt;li&gt; When a game ends, the enclave determines the winner and loser, then signs that result (e.g., &lt;code&gt;hash("winner:0x123,loser:0x456")&lt;/code&gt;) with its private key.&lt;/li&gt;
&lt;li&gt; The backend receives the result &lt;em&gt;and&lt;/em&gt; the signature.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This creates a verifiable chain of trust:&lt;br&gt;
&lt;code&gt;Intel CPU -&amp;gt; Attests Enclave Code -&amp;gt; Enclave Attests its Public Key -&amp;gt; Public Key Verifies Game Result Signature&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A user can now check the signature on the game result and be 100% certain it came from the verified enclave, not a tampered backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Final 0.01%: The Data Transport Problem &amp;amp; The Path to Perfection
&lt;/h3&gt;

&lt;p&gt;This brings us to the core dilemma you might be thinking of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Okay, the &lt;em&gt;computation&lt;/em&gt; is fair. But what if you, the admin, just delay my click packet before you even send it to the enclave?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You are absolutely right. This is the one vector SGX cannot solve on its own. The enclave is a trusted &lt;em&gt;computation&lt;/em&gt; environment, not a trusted &lt;em&gt;transport&lt;/em&gt; layer. The backend server's operating system is still responsible for receiving network packets and forwarding them to the enclave process.&lt;/p&gt;

&lt;p&gt;If I were truly malicious and technically sophisticated, I could write a kernel-level driver that artificially delays packets before handing them off to the enclave. The enclave would honestly record the later time, and that player would lose.&lt;/p&gt;

&lt;p&gt;We have achieved &lt;strong&gt;99.99% fairness&lt;/strong&gt;. To close that final gap and reach 100% trustless execution, we need hardware that protects the network stack itself.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Future: SmartNICs and Military-Grade Security
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuowvczyhbz0d3yln9ks.jpg" 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%2Fwuowvczyhbz0d3yln9ks.jpg" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a bootstrapped startup, we are pushing the limits of what's possible with current resources. But our roadmap includes an upgrade that will rival the security of top-tier crypto exchanges and banks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;SmartNICs (e.g., NVIDIA BlueField):&lt;/strong&gt; These are network cards with their own processors and secure enclaves. They can terminate TLS connections and timestamp packets &lt;em&gt;in hardware&lt;/em&gt; before they even reach the main server's OS. This eliminates the "kernel delay" attack vector entirely.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Hardware Attestation for Network:&lt;/strong&gt; Just like SGX, modern SmartNICs support SPDM (Security Protocol and Data Model), allowing us to prove that the network card's firmware hasn't been tampered with.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Physical HSM (YubiKey):&lt;/strong&gt; We plan to deploy a custom bare-metal server where critical keys are protected by a physical Hardware Security Module (HSM) like a YubiKey inserted directly into the machine. This ensures that even with root access, no one can extract the private keys.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Bonus: Securing the Keys to the Kingdom
&lt;/h4&gt;

&lt;p&gt;I'm also working on migrating our entire secret management system into SGX. Currently, we use a GPG-based system to secure keys for our microservices (read more about it in my &lt;a href="https://dev.to/crow004/-how-i-built-a-fully-decentralized-on-chain-game-with-0-lines-of-code-thanks-to-gemini-1d0p"&gt;previous article&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The goal is to move these secrets into an SGX enclave and delete them from the host machine entirely. This means that even if an attacker gains full root access to the server, they cannot steal the private keys used to sign transactions. This is &lt;strong&gt;military-grade protection&lt;/strong&gt; for a fun, casual game.&lt;/p&gt;

&lt;h3&gt;
  
  
  What About Decentralized Sequencers?
&lt;/h3&gt;

&lt;p&gt;We considered alternatives like the Hedera Consensus Service (HCS) or custom L3s. While fantastic for decentralized logging, they introduce &lt;strong&gt;latency&lt;/strong&gt; (3-5 seconds for finality). For a game where milliseconds matter, that's a dealbreaker.&lt;/p&gt;

&lt;p&gt;SGX provides the best of both worlds: the near-instantaneous speed of a centralized server with a level of computational integrity that is second only to a fully decentralized (and much slower) system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion: The 99.9% Solution
&lt;/h3&gt;

&lt;p&gt;We haven't just built a game; we've built a fortress of fairness. By combining Intel SGX, remote attestation, and end-to-end encryption, we've eliminated 99.99% of cheating vectors. And with our roadmap pointing towards SmartNICs and hardware-backed security, we are on a path to the theoretical 100%.&lt;/p&gt;

&lt;p&gt;This is transparency and security I'm proud to offer my players.&lt;/p&gt;

</description>
      <category>go</category>
      <category>web3</category>
      <category>security</category>
      <category>intel</category>
    </item>
    <item>
      <title>The Crypto Paradox: Why We Chase Memes While Ignoring Real Value</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Wed, 11 Feb 2026 06:01:37 +0000</pubDate>
      <link>https://forem.com/crow004/the-crypto-paradox-why-we-chase-memes-while-ignoring-real-value-30dh</link>
      <guid>https://forem.com/crow004/the-crypto-paradox-why-we-chase-memes-while-ignoring-real-value-30dh</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction: The Casino vs. The Company&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the traditional financial world, the giants of investing built their fortunes on a simple principle: &lt;strong&gt;invest in businesses, not tickers.&lt;/strong&gt; But walk into the crypto space today, and you’ll find a different reality. Investors are more likely to put $1,000 into a token named after a cartoon frog than into a decentralized application with thousands of users. Why are we so eager to gamble on "pump and dump" schemes while ignoring projects with actual utility?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1gbhstvyjs3wfdziq9nr.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%2F1gbhstvyjs3wfdziq9nr.png" alt="Buffett and Kiyosaki are mastering the " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Buffett Test: The 10-Year Rule&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Warren Buffett once famously said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If you aren’t willing to own a stock for ten years, don’t even think about owning it for ten minutes.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In crypto, we’ve flipped this on its head. Most participants aren't looking for a 10-year growth story; they are looking for a 10-minute 100x return. This "short-termism" is exactly what scammers pray on. Real projects, like the ones building on &lt;strong&gt;Base, Polygon, zkSync, or Optimism&lt;/strong&gt;, take time to develop. They have code, updates, and roadmaps. But to the average speculator, "real work" often looks like "slow growth."&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Kiyosaki and the "Homework" Gap&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Robert Kiyosaki, author of Rich Dad Poor Dad, always emphasized that &lt;strong&gt;investing is a team sport and requires "doing your homework."&lt;/strong&gt; In the stock market, this means digging into cash flow, management, and market fit.&lt;/p&gt;

&lt;p&gt;In crypto, "doing your homework" should mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading the Smart Contract (or checking if it's verified).&lt;/li&gt;
&lt;li&gt;Testing the dApp (Is it actually functional?).&lt;/li&gt;
&lt;li&gt;Looking at the Github (Is anyone actually coding?).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yet, many "investors" skip this homework entirely, buying tokens based on a Telegram shill. They aren't investing; they are donating their liquidity to sophisticated scammers.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The "Safe" Scam vs. The "Risky" Reality&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;It’s a strange paradox: people feel "safe" buying a token with 18 zeros in its price because it "could go to $1," yet they feel it’s "risky" to participate in a transparent, audited game or utility project.&lt;/p&gt;

&lt;p&gt;As a developer building &lt;strong&gt;&lt;a href="//muschairs.com"&gt;Musical Chairs&lt;/a&gt;&lt;/strong&gt;, I see this firsthand. We spend weeks perfecting the logic on zkSync and Binance Smart Chain, ensuring every transaction is fair and every reward is instant. This is the "real project" Kiyosaki talks about — an asset that generates value.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: A Shift in Strategy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Perhaps the only way to bridge this gap is to meet the market where it is. If the crowd wants tokens, give them a token — but one backed by a real engine. A token that doesn't just promise "the moon," but serves as a key to a functional ecosystem.&lt;/p&gt;

&lt;p&gt;It’s time we stop being "exit liquidity" for memes and start being "early adopters" of the next generation of the internet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1dit9yr90hf63y4jspc.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%2Fm1dit9yr90hf63y4jspc.png" alt="A bright future with Musical Chairs" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I've recently implemented this logic into Base, BSC, Polygon, Optimism and zkSync. Check out my progress here &lt;a href="https://github.com/crow-004/musical-chairs-game" rel="noopener noreferrer"&gt;https://github.com/crow-004/musical-chairs-game&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cryptocurrency</category>
      <category>investing</category>
      <category>web3</category>
      <category>warrenbuffett</category>
    </item>
    <item>
      <title>The Discipline Game: Why I Built a Web3 Classic with Zero Luck and Zero Tracking</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Sat, 17 Jan 2026 14:30:32 +0000</pubDate>
      <link>https://forem.com/crow004/the-discipline-game-why-i-built-a-web3-classic-with-zero-luck-and-zero-tracking-264p</link>
      <guid>https://forem.com/crow004/the-discipline-game-why-i-built-a-web3-classic-with-zero-luck-and-zero-tracking-264p</guid>
      <description>&lt;h2&gt;
  
  
  &lt;em&gt;In a world of noise, high-speed trading, and endless luck-based loops, I brought back the simplest test of human nerves — and put it on Arbitrum.&lt;/em&gt;
&lt;/h2&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xu5em1q51nh0mc6ymto.jpg" 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%2F0xu5em1q51nh0mc6ymto.jpg" alt=" " width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Dubai Hustle
&lt;/h3&gt;

&lt;p&gt;I live in Dubai. If you’ve ever been here, you know the vibe: everyone is rushing. Every second, someone is trying to outpace the other, whether it's in a supercar on Sheikh Zayed Road or a crowded metro car during rush hour. It’s a constant, high-stakes game of &lt;strong&gt;"Musical Chairs."&lt;/strong&gt; One moment the music is playing, the next — you’re either in the seat or you're out.&lt;/p&gt;

&lt;p&gt;That’s when it hit me. Why are all modern Web3 games so... complicated? We have complex staking, "Play-to-Earn" models that collapse in a week, and RNG (luck) that dictates who wins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where is the raw, human skill? Where is the discipline?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Concept: Pure Skill
&lt;/h3&gt;

&lt;p&gt;I decided to build &lt;a href="https://muschairs.com" rel="noopener noreferrer"&gt;Musical Chairs&lt;/a&gt;. No, not the one you remember from 5th grade, but a digital, on-chain version designed for the Web3 era. &lt;/p&gt;

&lt;p&gt;The philosophy is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;100% Skill-Based:&lt;/strong&gt; There is no "house edge." No randomized luck. Your success depends entirely on your reaction time and your nerves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-Chain Transparency:&lt;/strong&gt; Every move, every win, and every chair is handled by Arbitrum smart contracts. Total transparency, verified by the ledger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-Tracking Privacy:&lt;/strong&gt; I’m a firm believer in the original Web3 ethos. No cookies. No trackers. No selling your data to the highest bidder. Just you and the smart contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Arbitrum?
&lt;/h3&gt;

&lt;p&gt;To make this work, I needed speed. You can't play Musical Chairs on a slow network. I chose &lt;strong&gt;Arbitrum One&lt;/strong&gt; because it’s the only place where the "click" feels instant, the fees are negligible, and the security is inherited from Ethereum. It’s the perfect playground for a high-speed discipline test.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Trending" Moment
&lt;/h3&gt;

&lt;p&gt;I didn't expect the community to react this fast. We just hit the &lt;strong&gt;Trending list on PeerPush&lt;/strong&gt;, and the feedback has been insane. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuo6lplft97wetdhb1obb.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%2Fuo6lplft97wetdhb1obb.png" alt=" " width="390" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One user asked: &lt;em&gt;"What is my incentive to play?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My answer: &lt;strong&gt;To prove you're better than the crowd.&lt;/strong&gt; In Musical Chairs, the prize pool is player-funded. When you win, you aren't winning against a "house" — you are winning because you were more disciplined than the other participants. It’s the ultimate "Social PvP."&lt;/p&gt;

&lt;h3&gt;
  
  
  The Manifesto: No More Noise
&lt;/h3&gt;

&lt;p&gt;Web3 gaming is at a crossroads. We can either keep building Ponzi-nomics, or we can build games that actually test human limits. &lt;/p&gt;

&lt;p&gt;Musical Chairs is my protest against the noise. It’s a return to basics. It’s fast, it’s fair, and it’s live right now.&lt;/p&gt;




&lt;h3&gt;
  
  
  Join the Rush
&lt;/h3&gt;

&lt;p&gt;Are you disciplined enough to take the last chair? Or will you be left standing when the music stops?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎮 &lt;strong&gt;Play Now:&lt;/strong&gt; &lt;a href="https://muschairs.com" rel="noopener noreferrer"&gt;muschairs.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🗳️ &lt;strong&gt;Support us on PeerPush:&lt;/strong&gt; &lt;a href="https://peerpush.net/p/musical-chairs" rel="noopener noreferrer"&gt;Check the Trend&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Verify Stats:&lt;/strong&gt; &lt;a href="https://dune.com/crow004/musical-chairs-game-analytics" rel="noopener noreferrer"&gt;Dune Analytics&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📱 &lt;strong&gt;Community:&lt;/strong&gt; &lt;a href="https://t.me/muschairs" rel="noopener noreferrer"&gt;Telegram&lt;/a&gt; | &lt;a href="https://discord.gg/wnnJKjgfZW" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Built by a solo dev with a passion for privacy and pure competition. No VC, no fluff, just code.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How a Crypto-Miner Infiltrated My Umami Analytics (and How I Defeated It)</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Thu, 01 Jan 2026 09:56:43 +0000</pubDate>
      <link>https://forem.com/crow004/how-a-crypto-miner-infiltrated-my-umami-analytics-and-how-i-defeated-it-5adh</link>
      <guid>https://forem.com/crow004/how-a-crypto-miner-infiltrated-my-umami-analytics-and-how-i-defeated-it-5adh</guid>
      <description>&lt;p&gt;Building in public means sharing the wins, but it also means being honest about the technical challenges. Recently, my project &lt;strong&gt;Musical Chairs&lt;/strong&gt; faced a common but dangerous threat: an automated exploit targeted my self-hosted Umami analytics instance to install a Monero miner.&lt;/p&gt;

&lt;p&gt;Here is exactly what happened, how my architecture saved the host, and a guide to hardening your Docker setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Red Flag: Decoding the "Digest"
&lt;/h2&gt;

&lt;p&gt;It started when I checked my Docker logs. Instead of standard traffic, I saw Base64-encoded strings in the error reports. After decoding the &lt;code&gt;digest&lt;/code&gt; field, I found the output of a &lt;code&gt;top&lt;/code&gt; command showing a process named &lt;code&gt;next-server&lt;/code&gt; attempting to reserve &lt;strong&gt;10.4 GB of virtual memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Verdict:&lt;/strong&gt; My Umami container was compromised. An automated bot had gained access and was attempting to run a crypto-miner (&lt;code&gt;xmrig&lt;/code&gt; variant) disguised as a Next.js process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Hacker Failed (The Power of Isolation)
&lt;/h2&gt;

&lt;p&gt;Despite the container being compromised, the attacker &lt;strong&gt;never reached the host machine&lt;/strong&gt;. Two layers of my architecture worked exactly as intended:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Networking:&lt;/strong&gt; I used the &lt;code&gt;expose&lt;/code&gt; directive instead of &lt;code&gt;ports&lt;/code&gt;. Umami was only accessible via my Nginx Reverse Proxy internal network. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Limits:&lt;/strong&gt; In my &lt;code&gt;docker-compose.yml&lt;/code&gt;, I had strictly limited the container's memory to 1GB. When the miner tried to reserve 10GB of RAM, Docker’s resource management "choked" the process, preventing the host from freezing or crashing.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  The Recovery: Major Upgrade &amp;amp; Hardening
&lt;/h2&gt;

&lt;p&gt;If you are self-hosting Umami, simply restarting is not enough. You need to purge the old environment and upgrade to the latest major release.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Identify and Purge
&lt;/h3&gt;

&lt;p&gt;I killed the compromised instance and wiped the potentially "poisoned" image layers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose stop umami
docker compose &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; umami
&lt;span class="c"&gt;# Removing the old v2 image to prevent accidental reuse&lt;/span&gt;
docker rmi ghcr.io/umami-software/umami:postgresql-latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Upgrading to Umami v3 (Major Release)
&lt;/h3&gt;

&lt;p&gt;I updated my &lt;code&gt;docker-compose.yml&lt;/code&gt; to pull the latest major version and added strict resource quotas. Switching from &lt;code&gt;postgresql-latest&lt;/code&gt; (v2) to &lt;code&gt;latest&lt;/code&gt; (v3.0.3+) ensured I was on the most secure, up-to-date version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;umami&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/umami-software/umami:latest&lt;/span&gt; &lt;span class="c1"&gt;# Upgraded to major v3&lt;/span&gt;
    &lt;span class="na"&gt;expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000"&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1G&lt;/span&gt; &lt;span class="c1"&gt;# This killed the miner's memory hunger&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${DATABASE_URL}&lt;/span&gt;
      &lt;span class="na"&gt;HASH_SALT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${UMAMI_HASH_SALT}&lt;/span&gt;
      &lt;span class="na"&gt;APP_SECRET&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${UMAMI_HASH_SALT}&lt;/span&gt; &lt;span class="c1"&gt;# New requirement for Umami v3 / Next.js 15&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app_network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Updating Secrets
&lt;/h3&gt;

&lt;p&gt;The attacker likely exploited a weak or default &lt;code&gt;HASH_SALT&lt;/code&gt;. With the move to v3, I generated a new 32-character string for both &lt;code&gt;HASH_SALT&lt;/code&gt; and &lt;code&gt;APP_SECRET&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# Generating a new high-entropy secret&lt;/span&gt;
openssl rand &lt;span class="nt"&gt;-base64&lt;/span&gt; 32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Administrative Lockdown
&lt;/h3&gt;

&lt;p&gt;After pulling the fresh image and restarting:&lt;/p&gt;

&lt;p&gt;I immediately logged into the dashboard.&lt;/p&gt;

&lt;p&gt;Changed the default &lt;code&gt;admin/umami&lt;/code&gt; credentials to a unique, high-entropy password.&lt;/p&gt;

&lt;p&gt;Verified that the database migrations were successful &lt;strong&gt;— all historical data was preserved!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lessons Learned for Founders
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Limits are Mandatory:&lt;/strong&gt; Always set &lt;code&gt;deploy.resources.limits.memory&lt;/code&gt; in Docker. It prevents a single compromised container from crashing your entire VPS.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Major Upgrades Matter:&lt;/strong&gt; Don't get stuck on old major versions (like Umami v2). Newer versions often have better security defaults and more robust underlying frameworks like Next.js 15.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expose vs Ports:&lt;/strong&gt; Never map a port to &lt;code&gt;0.0.0.0&lt;/code&gt; unless it's your entry point (like Nginx).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Audit Your Logs:&lt;/strong&gt; If you see Base64 strings where they don't belong, decode them immediately. They are usually a "calling card" of an exploit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By sharing this, I hope to help other Web3 founders stay secure while they build. &lt;strong&gt;Musical Chairs&lt;/strong&gt; is now faster, more secure, and ready for our upcoming investment rounds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stay safe and keep building!&lt;/strong&gt; 🚀&lt;/p&gt;

</description>
      <category>web3</category>
      <category>security</category>
      <category>docker</category>
      <category>umami</category>
    </item>
    <item>
      <title>The Double-Edged Sword of "Flow State" in Game Dev ⚔️</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Thu, 11 Dec 2025 08:57:44 +0000</pubDate>
      <link>https://forem.com/crow004/the-double-edged-sword-of-flow-state-in-game-dev-5gbj</link>
      <guid>https://forem.com/crow004/the-double-edged-sword-of-flow-state-in-game-dev-5gbj</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Introduction: Chasing the Zen of Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For every developer, the "Flow State" is the holy grail. That feeling of complete immersion, where the gap between you and the code disappears, and you achieve peak focus without distraction. I’ve personally experienced the magic: hours feel like minutes, complex problems unravel effortlessly, and productivity skyrockets.&lt;/p&gt;

&lt;p&gt;It’s where the best game mechanics are born, and the most elegant code is written. But after years of chasing and achieving this state, I’ve realized it comes with a dangerous side effect: &lt;strong&gt;Flow is a perfect recipe for ignoring your body's survival signals.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Brilliant, Yet Blind, Power of Flow&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The psychological benefits of Flow, as defined by Mihaly Csikszentmihalyi, are undeniable. We get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;10x Output:&lt;/strong&gt; I can confidently say I've accomplished more in a 90-minute Flow session than in half a day of "normal" work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep Satisfaction:&lt;/strong&gt; The intrinsic reward of creation leads to higher job satisfaction and happiness.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accelerated Learning:&lt;/strong&gt; When your mind is fully engaged, new concepts and skills are absorbed faster.
However, the mechanism that makes Flow so powerful—the complete suppression of irrelevant stimuli—is precisely what makes it hazardous for long-term health.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Burnout Trap: What Flow Silences&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;My journey with Flow hit a wall when I realized I was consistently ignoring critical biological warnings:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Hydration and Nutrition Blackout:&lt;/strong&gt; I’d find myself emerging from a 3-hour session with a pounding headache and shaking hands, realizing I hadn't touched my water bottle or eaten anything since the morning. Your brain, prioritizing the complex problem, literally de-prioritizes basic sustenance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Sleep Debt Accumulator:&lt;/strong&gt; When you’re "in the zone," your brain effectively overrides fatigue signals. You push past the point where you should stop, telling yourself: "Just one more hour." This is how you accumulate severe sleep debt and pave the road to chronic burnout.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Physical Pain Blindness:&lt;/strong&gt; Only after the flow state dissipates do you realize that your neck has been locked at an awkward angle, your lower back is screaming, or your eyes are painfully strained from the intense focus.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Paradox:&lt;/strong&gt; We use Flow to be maximally productive, but by ignoring physical health, we decrease our overall capacity for future productive work.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;My 3 Non-Negotiable Rules for Safe Flow&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To harness the power of Flow without paying the price of burnout, I developed a simple system of boundaries. &lt;strong&gt;You must manage the Flow, not let the Flow manage you.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Strict Timer Rule (The 90-Minute Block):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Set a timer for 60 to 90 minutes. This is your maximum deep work block.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crucially:&lt;/strong&gt; When the timer goes off, STOP immediately. Get up. Walk away from the screen. Even if you feel like you are two minutes away from the solution, the break is more important.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Why 90 minutes?&lt;/em&gt; It aligns perfectly with your body's natural Ultradian rhythm—the cycle of high focus followed by a need for rest.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Pre-Flight Check (Before You Start):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Before you start the task, do a quick "body scan." Ask yourself: Am I adequately hydrated? Did I stretch my neck/back? Is my workstation ergonomic?&lt;/li&gt;
&lt;li&gt;Ensure your water bottle is full and a healthy snack is nearby. You are proactively eliminating the basic distractions before your mind has a chance to ignore them.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flow is an Accelerator, Not a Fuel Tank:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Understand that Flow is not a substitute for rest. It requires maximum energy output.&lt;/li&gt;
&lt;li&gt;If you are chronically sleep-deprived, the "Flow" you experience is often just hyper-focus fueled by stress (cortisol), not genuine high performance. Prioritize 7–8 hours of sleep to earn your next Flow session.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Flow State is the ultimate tool in the developer's arsenal, especially in the demanding, fast-paced world of Web3 and GameFi development. Use it. Embrace the feeling. But treat it with the respect it deserves, and never let it compromise your long-term health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are your strategies for maintaining balance while in deep focus? Share your thoughts below!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>mentalhealth</category>
      <category>web3</category>
      <category>developers</category>
    </item>
    <item>
      <title>The Divine Algorithm: A Developer’s Confession</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Sat, 22 Nov 2025 22:47:33 +0000</pubDate>
      <link>https://forem.com/crow004/the-divine-algorithm-a-developers-confession-30jd</link>
      <guid>https://forem.com/crow004/the-divine-algorithm-a-developers-confession-30jd</guid>
      <description>&lt;h3&gt;
  
  
  From the Void to the Verified Commit
&lt;/h3&gt;

&lt;p&gt;There is a specific kind of magic that happens when a programmer stares at a blank page. To the uninitiated, it is just a text editor; to me, it is the void before creation. I am not merely writing algorithms; I am breathing life into a vacuum. I am building a world.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Night Shift Symphony
&lt;/h3&gt;

&lt;p&gt;The paradox of this craft is energy. I can finish a grueling day at my "regular" job, feeling the weight of the world on my shoulders, completely drained. Yet, the moment I sit down to work on my passion project, that fatigue is stripped away as if by an invisible hand.&lt;/p&gt;

&lt;p&gt;Sleep becomes obsolete. Who needs sleep when the project itself feeds you energy? The code becomes a current running through my veins.&lt;/p&gt;

&lt;p&gt;There are nights when the cognitive load becomes so immense, so crushing, that I feel my mind might shatter. In those moments, I turn to classical music. The ordered complexity of a symphony saves me; it holds the chaos at bay, allowing my brain to dance rather than explode.&lt;/p&gt;

&lt;p&gt;And then, it happens. It is 5:00 or 6:00 in the morning. The world is asleep, but I am alive. I fix the last bug. I push the last commit. I stand up from the desk with a smile, filled with a profound, quiet satisfaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Infinite Horizon
&lt;/h3&gt;

&lt;p&gt;What keeps me going is the roadmap. It is a living thing. With every feature I implement, the horizon doesn't get closer—it gets wider. Every solved problem reveals three new possibilities, a fractal of potential that excites rather than daunts me.&lt;/p&gt;

&lt;p&gt;Then comes the release. The silence after publishing a post is electric. I sit and wait, heart pounding, for the first users. I crave their feedback. Even the criticism is a gift; if it is constructive, I accept it with gratitude. It is fuel for evolution.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Spiritual Compilation
&lt;/h3&gt;

&lt;p&gt;I believe this entire process flows from a higher power. Through my programs, I am not just exploring logic; I am exploring my own soul. I firmly believe this creativity comes from God.&lt;/p&gt;

&lt;p&gt;My journey hasn’t been linear. Initially, my greatest desire was to disappear. I sought the depths of anonymity, retreating into the shadows for months to be alone with the code. But once I satisfied that deep need for solitude, something shifted. The need to hide vanished.&lt;/p&gt;

&lt;p&gt;I emerged calmer. I felt as though I was walking hand-in-hand with God. I looked at what I had built and felt a new sensation: &lt;strong&gt;Self-Respect&lt;/strong&gt;. I had created something great.&lt;/p&gt;

&lt;p&gt;This newfound peace allowed me to do something that, for an extreme introvert, is akin to a heroic feat: I revealed my face. I uploaded my real photo to social media. I stepped out of the shadow and into the light, ready to communicate with the world.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Sandbox for the Future
&lt;/h3&gt;

&lt;p&gt;Now, my burning desire is to give this child of mine a life of its own. I want it to grow.&lt;/p&gt;

&lt;p&gt;I am building &lt;strong&gt;Musical Chairs&lt;/strong&gt; (&lt;a href="https://muschairs.com" rel="noopener noreferrer"&gt;https://muschairs.com&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;But this is more than a game. It is a vision. I am looking for those who can see the depth of this idea—the players, the contributors, the investors who want to inject lifeblood into a new economy. I am calling out to the Web3 enthusiasts and the blockchain pioneers who stood at the origins of this technology.&lt;/p&gt;

&lt;p&gt;I want this game to be the sandbox for &lt;strong&gt;mass adoption&lt;/strong&gt;. I want to show the world that blockchain is not just about charts and numbers; it is about connection, economy, and fun.&lt;/p&gt;

&lt;p&gt;I have poured my sleepless nights, my soul, and my peace into this. Now, I invite you to take a seat.&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>web3</category>
      <category>showdev</category>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Building Trust in DeFi: A Deep Dive into Musical Chairs' Time-Locked Emergency Functions</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Sat, 08 Nov 2025 00:00:14 +0000</pubDate>
      <link>https://forem.com/crow004/building-trust-in-defi-a-deep-dive-into-musical-chairs-time-locked-emergency-functions-41b</link>
      <guid>https://forem.com/crow004/building-trust-in-defi-a-deep-dive-into-musical-chairs-time-locked-emergency-functions-41b</guid>
      <description>&lt;h4&gt;
  
  
  &lt;em&gt;How we designed our smart contracts to protect player funds, even from ourselves.&lt;/em&gt;
&lt;/h4&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction: The Trust Problem in DeFi&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the world of decentralized finance (DeFi) and Web3 gaming, trust is the most valuable asset. We've all heard the horror stories: projects that vanish overnight, smart contract bugs that lock up user funds forever, and "rug pulls" where developers with privileged access drain the treasury. This creates a climate of fear that stifles innovation and scares away new users.&lt;/p&gt;

&lt;p&gt;At Musical Chairs, a simple, fast, and transparently fair on-chain game, we believe that building trust isn't about making promises; it's about writing code that makes those promises unbreakable.&lt;/p&gt;

&lt;p&gt;This article isn't just about our game. It's a deep dive into our design philosophy: Trust Through Transparency. We'll walk you through the specific, on-chain mechanisms we've implemented to safeguard player funds, focusing on the evolution of our &lt;code&gt;emergencyWithdrawal&lt;/code&gt; function from a powerful tool into a transparent, community-verifiable process.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Section 1: The Double-Edged Sword of "Owner" Power&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Any responsible smart contract needs a mechanism for maintenance and upgrades. An "owner" role is often necessary to deploy critical bug fixes or roll out new features. But this power is a double-edged sword. A malicious owner with instant access to critical functions poses the single greatest threat to a project's integrity.&lt;/p&gt;

&lt;p&gt;Our first version of the contract (MusicalChairs.sol) included a function for emergencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;solidity
 Show full code block 
// From MusicalChairs.sol (V1)
function emergencyWithdrawETH() external virtual onlyOwner nonReentrant {
    uint256 balance = address(this).balance;
    if (balance == 0) revert NoETHToWithdraw();
    (bool sent, ) = owner().call{value: balance}("");
    if (!sent) revert ETHEmergencyWithdrawalFailed();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function does its job—it allows the owner to recover all ETH from the contract in a catastrophe. But it has one major flaw in the context of user trust: &lt;strong&gt;it's instant.&lt;/strong&gt; A user would have no time to react. We knew we could do better.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Section 2: Our Solution — The Timelock as a Core Principle&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before we even tackled the emergency withdrawal, we established a core security principle for all critical administrative actions: the &lt;strong&gt;Timelock&lt;/strong&gt;. A timelock is a two-step process where an action is first publicly proposed and can only be executed after a predefined delay has passed.&lt;/p&gt;

&lt;p&gt;This is built into our contract's DNA. For example, changing the contract owner isn't a single transaction. It's a public, two-step process governed by a 7-day waiting period.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;solidity
 Show full code block 
// From MusicalChairs.sol
uint256 public constant DEFAULT_TIMELOCK_DELAY = 7 days;

function proposeNewOwner(address newOwnerCandidate) external virtual onlyOwner {
    // ... checks ...
    proposedNewOwner = newOwnerCandidate;
    ownerChangeProposalTimestamp = block.timestamp;
    emit OwnershipTransferProposed(newOwnerCandidate, block.timestamp + DEFAULT_TIMELOCK_DELAY);
}

function executeOwnerChange() external virtual {
    // ... checks ...
    if (block.timestamp &amp;lt; ownerChangeProposalTimestamp + DEFAULT_TIMELOCK_DELAY) revert TimelockNotPassed();
    _transferOwnership(proposedNewOwner);
    // ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This same timelock pattern is applied to changing the commission wallet and, most importantly, to upgrading the contract itself via our UUPS proxy. &lt;strong&gt;No critical change can happen without a 7-day public notice on the blockchain.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Section 3: The Evolution of Safety — emergencyWithdrawal V2&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With the timelock philosophy established, it was time to apply it to the &lt;code&gt;emergencyWithdrawal&lt;/code&gt; function. In our &lt;code&gt;MusicalChairsGameV2&lt;/code&gt; contract, we completely overhauled this mechanism.&lt;/p&gt;

&lt;p&gt;First, we permanently disabled the old, instant function. Calling it now will always fail.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;solidity
// From MusicalChairsGameV2.sol
function emergencyWithdrawETH() public pure override {
    revert EmergencyWithdrawalDeprecated();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we replaced it with a new, transparent, two-step timelocked process:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Propose the Withdrawal&lt;/strong&gt; The owner must first publicly declare their intent to withdraw funds. This function captures the entire contract balance at that moment and records a timestamp.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;solidity
 Show full code block 
// From MusicalChairsGameV2.sol
function proposeEmergencyWithdrawal() external virtual onlyOwner {
    uint256 balance = address(this).balance;
    if (emergencyWithdrawalProposalTimestamp != 0) revert EmergencyWithdrawalAlreadyProposed();
    if (balance == 0) revert NoETHToWithdraw();

    proposedEmergencyWithdrawalAmount = balance;
    emergencyWithdrawalProposalTimestamp = block.timestamp;
    emit EmergencyWithdrawalProposed(balance, block.timestamp + DEFAULT_TIMELOCK_DELAY);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Execute the Withdrawal (After 7 Days)&lt;/strong&gt; The funds can only be moved after the 7-day timelock has passed. If the owner tries to execute it even one second early, the transaction will revert.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;solidity
 Show full code block 
// From MusicalChairsGameV2.sol
function executeEmergencyWithdrawal() external virtual onlyOwner nonReentrant {
    if (emergencyWithdrawalProposalTimestamp == 0) revert NoEmergencyWithdrawalProposed();
    if (block.timestamp &amp;lt; emergencyWithdrawalProposalTimestamp + DEFAULT_TIMELOCK_DELAY) revert TimelockNotPassed();

    uint256 amountToWithdraw = proposedEmergencyWithdrawalAmount;
    // ... reset state variables ...

    (bool sent, ) = owner().call{value: amountToWithdraw}("");
    if (!sent) revert ETHEmergencyWithdrawalFailed();
    emit EmergencyWithdrawalExecuted(owner(), amountToWithdraw);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a night-and-day difference. The power to act in an emergency is retained, but the ability to abuse that power is eliminated. The community has a full week to see the proposal on-chain, discuss it, and, if necessary, exit the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: Our Commitment to Building in Public&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Our journey from an instant &lt;code&gt;emergencyWithdrawETH&lt;/code&gt; function in V1 to the two-step, time-locked process in V2 is more than just a technical upgrade; it's a statement of our core philosophy. We believe that true decentralization means designing systems that are safe &lt;em&gt;from&lt;/em&gt; their creators, not just &lt;em&gt;for&lt;/em&gt; them. By placing all critical functions behind a mandatory, on-chain delay, we give the ultimate power back to the community: the power of observation and the time to react.&lt;/p&gt;

&lt;p&gt;This commitment to transparency isn't just theoretical. Because every critical proposal—from ownership changes to contract upgrades—is subject to a 7-day timelock, these actions are public and verifiable on the blockchain long before they can be executed.&lt;/p&gt;

&lt;p&gt;To make this monitoring accessible to everyone, we've created a public Dune dashboard that tracks these on-chain events. While we've never had to propose an emergency withdrawal, you can see this timelock mechanism in action right now with our pending upgrade to V4. This dashboard shows exactly what was proposed and how much time is left on the clock before the action can be executed. It's a real-time example of our promise in action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1fcgjdtyyvlcezoyjec.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%2Fj1fcgjdtyyvlcezoyjec.png" alt=" " width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We invite you to be an active participant in our security. Dive into our code, ask us the tough questions in our community channels, and monitor our on-chain activity. Your scrutiny makes us stronger.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Review our Smart Contracts on GitHub:&lt;/strong&gt; github.com/crow-004/musical-chairs-contracts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interact with the live contract on Arbiscan:&lt;/strong&gt; arbiscan.io/address/0xEDA164585a5FF8c53c48907bD102A1B593bd17eF&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learn how to report a vulnerability:&lt;/strong&gt; View our SECURITY.md
Thank you for helping keep Musical Chairs secure!&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>solidity</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>security</category>
    </item>
    <item>
      <title>What Happens if We Get Hacked? A Transparent Look at the Musical Chairs Security Model</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Wed, 08 Oct 2025 12:33:42 +0000</pubDate>
      <link>https://forem.com/crow004/what-happens-if-we-get-hacked-a-transparent-look-at-the-musical-chairs-security-model-4mip</link>
      <guid>https://forem.com/crow004/what-happens-if-we-get-hacked-a-transparent-look-at-the-musical-chairs-security-model-4mip</guid>
      <description>&lt;p&gt;In the world of Web3, trust isn't given; it's built. And a huge part of that trust comes from a project's security model. When you're building a game that handles user funds, you can't just hope for the best. You have to plan for the worst.&lt;/p&gt;

&lt;p&gt;That's why, from day one, Musical Chairs was designed with a core principle in mind: &lt;strong&gt;separation of concerns&lt;/strong&gt;. Instead of a single, all-powerful "god key," our system uses three distinct private keys, each with a strictly limited set of permissions. This architecture is designed to minimize the "blast radius" if any single key were ever compromised.&lt;/p&gt;

&lt;p&gt;Let's be transparent and walk through what an attacker could—and, more importantly, &lt;em&gt;could not&lt;/em&gt;—do in each hypothetical scenario.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 1: The Backend Key is Compromised
&lt;/h3&gt;

&lt;p&gt;This is our "hottest" key. The backend server uses it to perform its one and only on-chain function: declaring the loser of a game round. It's the most exposed key, but also the one with the least power.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What could an attacker do?&lt;/strong&gt;&lt;br&gt;
An attacker with this key could disrupt gameplay. They could send invalid "loser declaration" transactions to the smart contract, causing active game rounds to get stuck or fail to resolve correctly. It would be a denial-of-service attack on the game's logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What could they NOT do?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; steal player funds locked in the contract.&lt;/li&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; change the game's rules, like the &lt;code&gt;stakeAmount&lt;/code&gt; or &lt;code&gt;commissionAmount&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; withdraw the accumulated platform commissions.&lt;/li&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; upgrade the contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt;&lt;br&gt;
Because this key's only role is to be the designated "loser-picker," the contract's Owner can simply revoke its address and assign a new, secure backend key. Gameplay would be restored quickly. The damage is limited to temporary disruption, not loss of funds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 2: The Owner Key is Compromised
&lt;/h3&gt;

&lt;p&gt;This is our administrative key. It's the most powerful of the three, which is why it is kept in secure, air-gapped cold storage and is used very infrequently. Its purpose is to manage the contract's parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What could an attacker do?&lt;/strong&gt;&lt;br&gt;
An attacker with the Owner key could propose changes to the contract's rules. They could attempt to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Change the &lt;code&gt;stakeAmount&lt;/code&gt; or &lt;code&gt;commissionAmount&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  Change the designated &lt;code&gt;backendAddress&lt;/code&gt; to one they control.&lt;/li&gt;
&lt;li&gt;  Propose an upgrade to a new, malicious implementation contract.&lt;/li&gt;
&lt;li&gt;  Propose changing the owner's address and the address for withdrawing the commission.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What could they NOT do?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; directly access or steal player funds already deposited in active games. The functions for depositing, claiming winnings, or requesting refunds are permissionless and controlled by the players themselves.&lt;/li&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; steal the platform's accumulated commission fees, as those are sent to a completely separate wallet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mitigation: The Timelock &amp;amp; Future Plans&lt;/strong&gt;&lt;br&gt;
This is our most critical line of defense. &lt;strong&gt;Every single administrative function controlled by the Owner is protected by a 7-day timelock.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If an attacker were to compromise this key and propose a malicious change (e.g., setting the commission to 100%), that change would be publicly visible on-chain for a full week before it could be executed. This gives the community and the team ample time to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Detect and publicize the malicious proposal.&lt;/li&gt;
&lt;li&gt; Encourage all players to safely withdraw their funds from the contract.&lt;/li&gt;
&lt;li&gt; Take measures to deploy a new, secure version of the contract and migrate the community.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The timelock turns a potential catastrophe into a manageable (though serious) incident, ensuring player funds remain safe.&lt;/p&gt;

&lt;p&gt;Furthermore, we plan to upgrade the Owner role to a &lt;strong&gt;2-of-3 multi-signature wallet&lt;/strong&gt; in the future. This will eliminate a single point of failure. Even if one of the three keys is compromised, an attacker would not be able to approve malicious proposals, and the remaining two key holders could securely replace the compromised key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario 3: The Commission Wallet Key is Compromised
&lt;/h3&gt;

&lt;p&gt;This key belongs to a standard wallet (EOA) designated to receive the platform's commission fees. It has no special privileges in the smart contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What could an attacker do?&lt;/strong&gt;&lt;br&gt;
They could steal all the funds &lt;strong&gt;currently inside that specific wallet&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What could they NOT do?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; affect gameplay.&lt;/li&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; steal player funds.&lt;/li&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; change any contract parameters.&lt;/li&gt;
&lt;li&gt;  They &lt;strong&gt;cannot&lt;/strong&gt; redirect future commissions to a different wallet (that requires the Owner key and is subject to the timelock).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mitigation:&lt;/strong&gt;&lt;br&gt;
The smart contract is designed to automatically transfer accumulated fees to the commission wallet as soon as they reach a minimal threshold (currently ~0.01 ETH). This prevents large sums from ever accumulating in the contract itself. From this commission wallet, funds are regularly withdrawn to cover operational expenses such as company registration, salaries, and marketing costs. This regular withdrawal process minimizes the amount of capital at risk at any given time. If this key were compromised, the Owner would simply initiate a timelocked transaction to designate a new, secure &lt;code&gt;commissionRecipient&lt;/code&gt; address. The impact is limited only to the funds held in that wallet at that moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion: Building for Resilience
&lt;/h3&gt;

&lt;p&gt;No system is 100% "unhackable," but a well-designed system is resilient. By separating the keys for gameplay, administration, and finance, we ensure that the failure of one component does not lead to the failure of the entire system.&lt;/p&gt;

&lt;p&gt;This multi-key architecture, combined with on-chain timelocks and a clear roadmap for further decentralization, is our commitment to you. We believe that building in the open and being transparent about our security model is the only way to build lasting trust in the Web3 space.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happens if the Server Itself is Compromised? The "Root Access" Scenario
&lt;/h3&gt;

&lt;p&gt;This is the ultimate test for any application handling funds: what happens if an attacker gains root access to the production server? This scenario assumes the attacker has bypassed all network-level defenses and has full control over the machine running our backend and its related services.&lt;/p&gt;

&lt;p&gt;Our security model is designed with a defense-in-depth approach, so even in this "doomsday" scenario, the damage is contained.&lt;/p&gt;

&lt;h4&gt;
  
  
  What an Attacker Would Find
&lt;/h4&gt;

&lt;p&gt;First, it's important to note what is &lt;strong&gt;not&lt;/strong&gt; on the server: there is no source code. The backend and &lt;code&gt;keyservice&lt;/code&gt; are compiled Go executables. Furthermore, they are obfuscated using &lt;code&gt;garble&lt;/code&gt; and compressed with &lt;code&gt;upx&lt;/code&gt;, making reverse-engineering a non-trivial, time-consuming task.&lt;/p&gt;

&lt;p&gt;The primary target for an attacker would be the private key for the &lt;code&gt;backendAddress&lt;/code&gt;, which is used for operational tasks like creating games and recording results. This key is stored as a Docker secret, which translates to a file on the host machine with permissions restricted to the root user (&lt;code&gt;chmod 600&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;As we've covered, the impact of a compromised backend key is limited to gameplay disruption, not the loss of user or platform funds.&lt;/p&gt;

&lt;h4&gt;
  
  
  The "Master Key" Fallback and Our Roadmap to Eliminating On-Disk Keys
&lt;/h4&gt;

&lt;p&gt;The backend has a unique, last-resort recovery mechanism for the &lt;code&gt;keyservice&lt;/code&gt;. It contains a heavily obfuscated module holding GPG-encrypted copies of the key file and its credentials. The encryption is intentionally slow and computationally expensive, using military-grade &lt;code&gt;AES256&lt;/code&gt; with a high &lt;code&gt;s2k-count&lt;/code&gt;, making it resilient against brute-force attacks, even from future quantum computers using Grover's algorithm.&lt;/p&gt;

&lt;p&gt;However, our long-term goal is to &lt;strong&gt;eliminate the presence of key files on the server altogether&lt;/strong&gt;. We are actively researching two primary paths forward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hardcoded, In-Memory Keys:&lt;/strong&gt; Transitioning to a model where encrypted key data is hardcoded directly into the obfuscated binary. The key would only ever exist in memory during the brief moment of a transaction's signing, removing the attack vector of a compromised file system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Confidential Computing:&lt;/strong&gt; In the future, we plan to migrate to servers that offer encrypted memory enclaves (like Intel SGX or AMD SEV). This would allow us to run the &lt;code&gt;keyservice&lt;/code&gt; in a completely isolated, encrypted portion of RAM, making it inaccessible even to a compromised host operating system. While this technology is still maturing and currently expensive, it represents the gold standard for key security that we are aiming for.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By combining strong, quantum-resistant encryption today with a clear roadmap toward eliminating on-disk secrets, we are committed to a continuous process of hardening our infrastructure. This layered approach is fundamental to our security philosophy: trust nothing, verify everything, and limit the blast radius of any potential compromise.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>web3</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>What is Gin? A Deep Dive into the Go Web Framework in Our Project</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Wed, 01 Oct 2025 19:40:21 +0000</pubDate>
      <link>https://forem.com/crow004/what-is-gin-a-deep-dive-into-the-go-web-framework-in-our-project-20n</link>
      <guid>https://forem.com/crow004/what-is-gin-a-deep-dive-into-the-go-web-framework-in-our-project-20n</guid>
      <description>&lt;p&gt;If you've looked through our backend code, you've probably seen the name &lt;strong&gt;Gin&lt;/strong&gt; pop up frequently. What is it, and why is it so central to our application?&lt;/p&gt;

&lt;p&gt;In short, Gin is a high-performance web framework for the Go programming language. It provides a robust set of tools that simplifies the process of building web servers and APIs, like the one that powers our game. Instead of writing a lot of boilerplate code to handle HTTP requests, routing, and JSON manipulation, we use Gin's ready-made, optimized functions.&lt;/p&gt;

&lt;p&gt;Let's break down what that means and how we use its core features in our project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Middleware Analogy: An Assembly Line for Requests
&lt;/h2&gt;

&lt;p&gt;One of the most powerful concepts in Gin is &lt;strong&gt;middleware&lt;/strong&gt;. To understand it, imagine a factory assembly line. Before the main worker (your API handler, like &lt;code&gt;handleRequestJoinNonce&lt;/code&gt;) receives a part (the HTTP request), it passes through several automated stations.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Station 1 (Logger):&lt;/strong&gt; Records that a new part has arrived.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Station 2 (Security Check):&lt;/strong&gt; Verifies the part meets standards (e.g., checks CORS headers).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Station 3 (Authentication):&lt;/strong&gt; Checks if the part has the right credentials (e.g., an auth token).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a part fails inspection at any station, it's removed from the line and never reaches the main worker. If it passes, it continues down the line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gin's middleware functions are these stations.&lt;/strong&gt; They are functions that execute &lt;em&gt;before&lt;/em&gt; or &lt;em&gt;after&lt;/em&gt; your main request handler. They form a chain, and each one performs a specific, isolated task.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Middleware Works in Our Project
&lt;/h2&gt;

&lt;p&gt;In our &lt;code&gt;cmd/server/main.go&lt;/code&gt;, you can see how we set up this "assembly line" for all incoming requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Default Setup: &lt;code&gt;gin.Default()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This simple call automatically adds two essential pieces of middleware:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;gin.Logger()&lt;/code&gt;: This logs every incoming request to the console, showing the HTTP method, path, status code, and response time. It's invaluable for debugging.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;gin.Recovery()&lt;/code&gt;: This acts as a safety net. If a &lt;code&gt;panic&lt;/code&gt; occurs anywhere in your handler code, this middleware catches it, prevents the entire server from crashing, and returns a &lt;code&gt;500 Internal Server Error&lt;/code&gt; response to the client.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. CORS Middleware: &lt;code&gt;router.Use(cors.New(corsConfig))&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;CORS (Cross-Origin Resource Sharing) is a browser security feature. This middleware handles it for us. When a request comes from a different domain (like our frontend), this middleware checks if that domain is on our allowed list. If it is, it adds the necessary &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; headers to the response so the browser doesn't block it. If not, it can abort the request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// From cmd/server/main.go&lt;/span&gt;
&lt;span class="n"&gt;corsConfig&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;AllowOrigins&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;getAllowedOrigins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowedOrigins&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;AllowMethods&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OPTIONS"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;AllowHeaders&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Origin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Upgrade"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;AllowCredentials&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corsConfig&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Sentry Middleware: router.Use(sentrygin.New(sentrygin.Options{}))
&lt;/h3&gt;

&lt;p&gt;This middleware integrates our server with Sentry for error tracking. Like the recovery middleware, it wraps our handlers. If an error or panic occurs, it captures detailed context about the request and sends a comprehensive report to Sentry, helping us debug issues in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Request Flow Visualized
&lt;/h2&gt;

&lt;p&gt;So, when a client sends a POST request to /api/v1/join, here’s the journey:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Request arrives at Gin.&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;2. gin.Logger()&lt;/strong&gt; runs, logs the request details, and passes control to the next station.&lt;br&gt;
&lt;strong&gt;3. cors.New(...)&lt;/strong&gt; runs, checks the Origin header, adds response headers, and passes control on.&lt;br&gt;
&lt;strong&gt;4. sentrygin.New(...)&lt;/strong&gt; runs, setting up its error-catching net, and passes control on.&lt;br&gt;
&lt;strong&gt;5. h.handleRequestJoinNonce&lt;/strong&gt; (our main handler) finally runs. It does its job, generates a nonce, and prepares a JSON response.&lt;br&gt;
&lt;strong&gt;6. Control returns back up the chain.&lt;/strong&gt; Sentry sees no errors. The logger records the final status (e.g., 200 OK) and total time.&lt;br&gt;
&lt;strong&gt;7. The final response is sent to the client.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Other Key Gin Features We Use
&lt;/h2&gt;

&lt;p&gt;Beyond middleware, Gin provides other essential tools that we rely on:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Routing:&lt;/strong&gt; Gin's core strength is its fast and flexible router. It lets us cleanly map URLs to specific handler functions, as seen in our internal/api/routes.go file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// From internal/api/routes.go&lt;/span&gt;
&lt;span class="n"&gt;apiV1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/api/v1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;apiV1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/join"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handleRequestJoinNonce&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;apiV1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/game/:gameId/status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;handleGetGameStatus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JSON Binding and Rendering:&lt;/strong&gt; Gin makes working with JSON effortless. It can automatically parse an incoming JSON request body into a Go struct (c.ShouldBindJSON(&amp;amp;req)) and serialize a Go struct or map into a JSON response (c.JSON(...)). This saves us from manual JSON marshaling and unmarshaling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// From internal/api/handlers.go&lt;/span&gt;
&lt;span class="c"&gt;// Reading JSON from a request into a struct&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShouldBindJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Sending a struct as a JSON response&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RequestJoinNonceResponse&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Nonce&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In essence, Gin is the skeleton of our web server. It handles the repetitive, complex, and error-prone parts of web development, allowing us to focus on what makes our application unique: the game logic. By providing features like a high-speed router, a powerful middleware system, and easy JSON handling, it helps us build a more robust, maintainable, and performant backend.&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>backend</category>
    </item>
    <item>
      <title>The Transparency Paradox: I Open-Sourced My Web3 Game's Contracts, But Kept The Backend Secret. Here's Why.</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Wed, 17 Sep 2025 13:40:29 +0000</pubDate>
      <link>https://forem.com/crow004/the-transparency-paradox-i-open-sourced-my-web3-games-contracts-but-kept-the-backend-secret-2bop</link>
      <guid>https://forem.com/crow004/the-transparency-paradox-i-open-sourced-my-web3-games-contracts-but-kept-the-backend-secret-2bop</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%2Fvgt49m6wytswwexnvwl1.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%2Fvgt49m6wytswwexnvwl1.png" alt="Game Banner" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a moment of sheer terror that every Web3 founder faces. It's not the fear of a bug, a market crash, or an empty Discord. It's the moment you hover your mouse over the "Make Public" button on your source code repository.&lt;/p&gt;

&lt;p&gt;For months, this code has been your secret. Your intellectual property. Your competitive edge. Making it public feels like you're not just opening the door to your house; you're handing out the blueprints and a set of keys.&lt;/p&gt;

&lt;p&gt;Today, I did just that for my on-chain game, &lt;a href="https://muschairs.com" rel="noopener noreferrer"&gt;Musical Chairs&lt;/a&gt;. The smart contracts that govern the game, hold the funds, and define the rules are now fully open source. But the backend code that runs the game logic remains proprietary.&lt;/p&gt;

&lt;p&gt;This isn't a compromise. It's a strategy. And it's at the very heart of the Web3 paradox: how to build a transparent, trustless system without giving away the kingdom.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Web3 Promise: Trust, Don't Verify? No, Trust &lt;em&gt;Because&lt;/em&gt; You Can Verify.
&lt;/h3&gt;

&lt;p&gt;In the world of Web2, the "secret sauce" is everything. In Web3, the secret sauce is that there &lt;em&gt;is&lt;/em&gt; no secret sauce on-chain. The core value proposition of our entire industry is that users don't have to trust a person or a company; they can trust the code.&lt;/p&gt;

&lt;p&gt;But they can only trust the code if they can see it.&lt;/p&gt;

&lt;p&gt;A closed-source smart contract handling user funds is a massive red flag. It asks for blind faith in a space designed to eliminate it. That's why, as a foundational step, I've open-sourced all the smart contracts for Musical Chairs under the MIT license.&lt;/p&gt;

&lt;p&gt;➡️ &lt;strong&gt;You can view them all here: &lt;a href="https://github.com/crow-004/musical-chairs-contracts" rel="noopener noreferrer"&gt;github.com/crow-004/musical-chairs-contracts&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This means anyone can now verify that our game does exactly what it says on the tin. No backdoors. No hidden fees. No "rug-pull" functions. Just code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fear is Real: "But What About the Hackers?"
&lt;/h3&gt;

&lt;p&gt;The first thought that paralyzes any developer is: "By showing everyone the locks, am I just giving hackers the keys?"&lt;/p&gt;

&lt;p&gt;It's a valid fear. But the concept of "security through obscurity" is a myth that has been debunked time and time again. A determined attacker can decompile your bytecode. Hiding your source code only stops the good guys from helping you.&lt;/p&gt;

&lt;p&gt;I learned this firsthand. A few days ago, a white-hat hacker named &lt;strong&gt;Harun&lt;/strong&gt; reached out. He had found a vulnerability—not in the contract, but in the domain's DNS configuration, which could have allowed for email spoofing and sophisticated phishing attacks. He didn't exploit it; he reported it responsibly. We fixed it and rewarded him for his efforts.&lt;/p&gt;

&lt;p&gt;This is the power of "many good eyes" over the "one bad actor." By opening the code, you aren't just inviting scrutiny; you are inviting a global, decentralized security team to help you build a stronger fortress.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Developer's Guide to Provable Code
&lt;/h3&gt;

&lt;p&gt;Opening your code is step one. Step two is proving that the open-source code is the &lt;em&gt;exact&lt;/em&gt; code running on the blockchain. This is where many developers stumble.&lt;/p&gt;

&lt;p&gt;The key lies in a humble file your compiler generates: &lt;code&gt;metadata.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Think of this file as your contract's "digital passport." It contains the compiler version, settings, and hashes of all your source files. When you upload this file and your source code to a service like Sourcify, it can recompile your code and verify, with cryptographic certainty, that it produces the exact same bytecode that's on-chain. This is the ultimate "social proof" in our industry—or more accurately, &lt;em&gt;verifiable proof&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If you're using Hardhat, extracting this metadata is simple. You can create a small task like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// file: hardhat.config.ts&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;task&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;hardhat/config&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;fs&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;fs&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;path&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;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;export-metadata&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Exports the metadata file for a contract&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;addParam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;contract&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The fully qualified name of the contract (e.g., 'contracts/MyContract.sol:MyContract')&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;setAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buildInfo&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;artifacts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBuildInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;taskArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contract&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="nx"&gt;buildInfo&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;sourceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contractName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;taskArgs&lt;/span&gt;&lt;span class="p"&gt;.&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:&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;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;buildInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sourceName&lt;/span&gt;&lt;span class="p"&gt;]?.[&lt;/span&gt;&lt;span class="nx"&gt;contractName&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;metadata&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="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;metadata.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;metadata&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;✅ Metadata exported!&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;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;npx hardhat export-metadata --contract "contracts/MusicalChairs.sol:MusicalChairsGame"&lt;/code&gt; gives you the exact file you need. This small step is what separates "source-available" from "source-verified."&lt;/p&gt;

&lt;h3&gt;
  
  
  The Strategy: The "Transparent Core" Model
&lt;/h3&gt;

&lt;p&gt;So, if transparency is so important, why isn't the backend code public?&lt;/p&gt;

&lt;p&gt;Because my goal is to build a sustainable business, not just a weekend project. The smart contracts are the &lt;strong&gt;"Transparent Core."&lt;/strong&gt; They are the public constitution, the immutable laws of the game that protect the user.&lt;/p&gt;

&lt;p&gt;The backend, however, is the &lt;strong&gt;"Proprietary Engine."&lt;/strong&gt; It contains the unique logic for player matchmaking, real-time communication, anti-bot measures, and performance optimizations. This is our competitive advantage. Open-sourcing it at this early stage would be like a Formula 1 team publishing the blueprints to their engine mid-season. A larger, better-funded team could simply copy it and out-market us into oblivion.&lt;/p&gt;

&lt;p&gt;This hybrid approach provides the best of both worlds: on-chain trust and off-chain competitive advantage.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Road Ahead: Audits and Accountability
&lt;/h3&gt;

&lt;p&gt;My commitment to transparency doesn't stop here. This is a journey, and we're #buildinginpublic.&lt;/p&gt;

&lt;p&gt;While the backend code will remain closed for now, I want to provide assurances of its integrity. That's why, once the game starts generating meaningful revenue, &lt;strong&gt;the very first investment will be a professional, third-party audit of the backend code&lt;/strong&gt; by a reputable cybersecurity firm. The goal will be to get a public report confirming that the server-side logic is fair, secure, and contains no malicious functions.&lt;/p&gt;

&lt;p&gt;This is how you build a real business in Web3. Not by hiding, but by layering proofs of integrity, one on top of the other.&lt;/p&gt;

&lt;p&gt;This journey is terrifying, exhilarating, and deeply rewarding. If you're a developer on the fence about opening your code, I hope my story helps. It's not about giving everything away. It's about building trust in a trustless world. And that, ultimately, is the most valuable asset you can have.&lt;/p&gt;




&lt;h3&gt;
  
  
  About the Author
&lt;/h3&gt;

&lt;p&gt;If you enjoyed this technical deep dive, you might like my current project: &lt;strong&gt;&lt;a href="https://muschairs.com" rel="noopener noreferrer"&gt;Musical Chairs&lt;/a&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;It’s a 100% skill-based competition on Arbitrum, built with the same focus on privacy and clean code (and yes, zero trackers). &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎮 &lt;strong&gt;Play the game:&lt;/strong&gt; &lt;a href="https://muschairs.com" rel="noopener noreferrer"&gt;muschairs.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🛠️ &lt;strong&gt;Check the source:&lt;/strong&gt; &lt;a href="https://github.com/crow-004/musical-chairs-game" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📈 &lt;strong&gt;Follow the official links:&lt;/strong&gt; &lt;a href="https://muschairs.com/links.html" rel="noopener noreferrer"&gt;Musical Chairs Official Links&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>web3</category>
      <category>solidity</category>
      <category>buildinpublic</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Demystifying CORS: A Practical Guide for Go Developers</title>
      <dc:creator>crow</dc:creator>
      <pubDate>Sat, 23 Aug 2025 11:58:37 +0000</pubDate>
      <link>https://forem.com/crow004/demystifying-cors-a-practical-guide-for-go-developers-11fj</link>
      <guid>https://forem.com/crow004/demystifying-cors-a-practical-guide-for-go-developers-11fj</guid>
      <description>&lt;h2&gt;
  
  
  A deep dive into what Cross-Origin Resource Sharing (CORS) is, why it exists, and how to correctly configure it in a Go web server using the Gin framework.
&lt;/h2&gt;

&lt;p&gt;If you've ever built a web application with a separate frontend and backend, you've almost certainly run into this dreaded error in your browser's console:&lt;/p&gt;

&lt;p&gt;Access to fetch at '&lt;a href="http://localhost:8080/api/v1/join" rel="noopener noreferrer"&gt;http://localhost:8080/api/v1/join&lt;/a&gt;' from origin '&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;' has been blocked by CORS policy...&lt;/p&gt;

&lt;p&gt;This error is a rite of passage for web developers. It can be frustrating, and the knee-jerk reaction is often to find a quick fix to "disable" it. But what if I told you that CORS isn't an error to be disabled, but a crucial security feature to be understood and configured correctly?&lt;/p&gt;

&lt;p&gt;Let's break down what CORS is, why it exists, and how we've implemented it properly in our Go project using the Gin framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Why": A Security Rule Called the Same-Origin Policy
&lt;/h2&gt;

&lt;p&gt;To understand CORS, you first need to understand the &lt;strong&gt;Same-Origin Policy (SOP)&lt;/strong&gt;. It's a fundamental security rule built into every modern web browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's a simple analogy:&lt;/strong&gt; Imagine your backend server is an exclusive, members-only club. The Same-Origin Policy is the club's main rule: "You can only make requests and get data from people &lt;em&gt;already inside&lt;/em&gt; this club."&lt;/p&gt;

&lt;p&gt;An "origin" is defined by the combination of a protocol (like &lt;code&gt;http&lt;/code&gt;), a hostname (like &lt;code&gt;my-game.com&lt;/code&gt;), and a port (like &lt;code&gt;:8080&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A script on &lt;code&gt;https://my-game.com&lt;/code&gt; requesting data from &lt;code&gt;https://my-game.com/api/status&lt;/code&gt; is &lt;strong&gt;the same origin&lt;/strong&gt;. The request is allowed.&lt;/li&gt;
&lt;li&gt;  A script on &lt;code&gt;https://my-game.com&lt;/code&gt; requesting data from &lt;code&gt;https://api.my-game.com&lt;/code&gt; is a &lt;strong&gt;different origin&lt;/strong&gt; (subdomain differs).&lt;/li&gt;
&lt;li&gt;  A script on &lt;code&gt;http://localhost:3000&lt;/code&gt; (your frontend) requesting data from &lt;code&gt;http://localhost:8080&lt;/code&gt; (your backend) is a &lt;strong&gt;different origin&lt;/strong&gt; (port differs).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When your frontend tries to make a request to your backend, the browser sees it's going to a different "club" and, by default, blocks it for security reasons. This prevents a malicious website, say &lt;code&gt;evil.com&lt;/code&gt;, from making authenticated requests to your bank's API (&lt;code&gt;your-bank.com/api&lt;/code&gt;) using your browser's cookies.&lt;/p&gt;

&lt;p&gt;So, how do we allow our legitimate frontend to talk to our backend?&lt;/p&gt;

&lt;h2&gt;
  
  
  The "How": CORS (Cross-Origin Resource Sharing)
&lt;/h2&gt;

&lt;p&gt;CORS is the mechanism that allows the "club" (your backend server) to tell the browser, "It's okay, I trust that other building (your frontend's origin). You can let their requests through."&lt;/p&gt;

&lt;p&gt;It’s not about disabling security; it’s about creating a list of trusted friends.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Preflight" Request: A Polite Conversation
&lt;/h3&gt;

&lt;p&gt;For any request that could modify data (like &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;, or any request with custom headers like &lt;code&gt;Content-Type: application/json&lt;/code&gt;), the browser doesn't send the request immediately. Instead, it sends a "preflight" request.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Browser Asks:&lt;/strong&gt; Before sending the real &lt;code&gt;POST&lt;/code&gt; request to &lt;code&gt;/api/v1/join&lt;/code&gt;, the browser sends a tiny, harmless &lt;code&gt;OPTIONS&lt;/code&gt; request to the same URL. It's essentially asking for permission: "Hey server, I'm a script from &lt;code&gt;http://localhost:3000&lt;/code&gt;. Are you okay with me sending a &lt;code&gt;POST&lt;/code&gt; request with a &lt;code&gt;Content-Type&lt;/code&gt; header?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Server Responds:&lt;/strong&gt; Your backend server, if configured for CORS, sees this &lt;code&gt;OPTIONS&lt;/code&gt; request and replies with a set of special headers. These headers are the server's answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;Access-Control-Allow-Origin: http://localhost:3000&lt;/code&gt; ("Yes, I allow requests from that specific origin.")&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;Access-Control-Allow-Methods: GET, POST, OPTIONS&lt;/code&gt; ("Yes, I allow these HTTP methods.")&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;Access-Control-Allow-Headers: Content-Type, Authorization&lt;/code&gt; ("Yes, I allow these headers to be sent.")&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Browser Decides:&lt;/strong&gt; If the server's response headers grant permission, the browser then sends the &lt;strong&gt;actual &lt;code&gt;POST&lt;/code&gt; request&lt;/strong&gt; with the JSON data. If the server &lt;em&gt;doesn't&lt;/em&gt; respond with these headers, the browser blocks the request and shows you the infamous CORS error.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  CORS in Action: Our Go &amp;amp; Gin Implementation
&lt;/h2&gt;

&lt;p&gt;This whole "conversation" is handled beautifully by middleware. In our project, we use the &lt;code&gt;gin-contrib/cors&lt;/code&gt; package. Let's look at the configuration in &lt;code&gt;cmd/server/main.go&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// --- CORS MIDDLEWARE SETUP ---&lt;/span&gt;
&lt;span class="n"&gt;corsConfig&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Here we list our "trusted friends"&lt;/span&gt;
    &lt;span class="n"&gt;AllowOrigins&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="n"&gt;getAllowedOrigins&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowedOrigins&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="c"&gt;// The methods we permit&lt;/span&gt;
    &lt;span class="n"&gt;AllowMethods&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OPTIONS"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="c"&gt;// The headers our frontend is allowed to send&lt;/span&gt;
    &lt;span class="n"&gt;AllowHeaders&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;     &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Origin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Upgrade"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="n"&gt;ExposeHeaders&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Content-Length"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;AllowCredentials&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;MaxAge&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;           &lt;span class="m"&gt;12&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Apply this CORS "policy" to all incoming requests&lt;/span&gt;
&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corsConfig&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c"&gt;// --- END OF CORS SETUP ---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we call &lt;code&gt;router.Use(cors.New(corsConfig))&lt;/code&gt;, we are inserting that "security check" station at the very beginning of our request processing assembly line.&lt;/p&gt;

&lt;p&gt;It intercepts every incoming request.&lt;br&gt;
If it's a preflight &lt;code&gt;OPTIONS&lt;/code&gt; request, it automatically sends back the correct &lt;code&gt;Access-Control-*&lt;/code&gt; headers based on our &lt;code&gt;corsConfig&lt;/code&gt;.&lt;br&gt;
If it's a regular &lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;POST&lt;/code&gt; request, it adds the &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; header to the response, confirming to the browser that the request was legitimate.&lt;br&gt;
All of this happens before our actual API handlers, like &lt;code&gt;handleRequestJoinNonce&lt;/code&gt;, are even touched. This keeps our handler code clean and focused on business logic, while the middleware handles the cross-origin security policy.&lt;/p&gt;

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

&lt;p&gt;CORS is not an error; it's a vital security feature of the web. Understanding the Same-Origin Policy and the preflight request flow turns a frustrating roadblock into a configurable part of your server's security posture. By using a middleware library like &lt;code&gt;gin-contrib/cors&lt;/code&gt;, you can implement a robust and secure policy with just a few lines of code, ensuring your frontend and backend can communicate safely and effectively.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>go</category>
      <category>backend</category>
      <category>security</category>
    </item>
  </channel>
</rss>
