$ solidity lab

A public build log. I'm learning how smart contracts actually work by writing, testing, and deploying one small contract at a time, working up a seven-project ladder from a piggy bank to a toy stablecoin. Everything runs on testnets with fake money.

Neil Patel · started 2026-07-27 · built with Foundry on Base Sepolia · code on GitHub

The ladder

▶1. PiggyBankdeposits, withdrawals, ownership, events
○2. ERC-20 tokenthe token standard, allowances, OpenZeppelin
○3. Token faucetrate limits, pull vs push payments
○4. Escrowstate machines, reentrancy, holding USDC
○5. Payment splitterrevenue shares, pull-payment accounting
○6. 2-of-3 multisigcontract wallets, low-level call
○7. Toy stablecoinoracles, collateral, liquidations

Build log · newest first

2026-07-29 session 2 1. PiggyBank

Going public: faucet, bridge, live deploy on Base Sepolia

What we did

  • Fixed the failed GitHub CI run: forge fmt --check wanted (bool ok,) not (bool ok, ); ran forge fmt, pushed, CI green in 19s
  • Claimed 0.05 test ETH from Google's faucet on Ethereum Sepolia (their list had dropped Base Sepolia)
  • Bridged 0.04 test ETH from Ethereum Sepolia to Base Sepolia by sending it to Base's official L1StandardBridge contract; it minted on L2 about a minute later
  • Deployed PiggyBank to Base Sepolia with forge create, a real public testnet anyone can inspect
  • Verified the source code on Blockscout, so the explorer shows readable Solidity instead of bytecode
  • Ran a public deposit (0.005 ETH) and withdrawAll against the live contract with cast

What I learned

  • Faucets are developer marketing: Google gives away worthless test ETH to sell RPC node access; Coinbase does it to attract builders to Base
  • Faucets only ever need your public address; anything asking for a private key is a scam
  • Bridging L1 to L2 can be as simple as sending ETH to the bridge contract, which mints it to your same address on the other chain
  • Contract addresses are deterministic (hash of deployer address + nonce), so the Base Sepolia deploy got the same address as the anvil one
  • Source verification uploads your code to the explorer, which recompiles it and checks the bytecode matches what is on chain
  • Public RPC endpoints are load balanced and can serve slightly stale state; a read right after a write may lag a block or two
  • CI emails titled Run failed mean a repo check failed; gh run view --log-failed shows exactly why

Next up

  • Project 2: write an ERC-20 token from scratch, then compare with OpenZeppelin
  • Learn the approve / transferFrom allowance pattern that underpins DeFi
2026-07-27 session 1 1. PiggyBank

Setup + first contract: PiggyBank

What we did

  • Installed Foundry 1.7.1 (forge, cast, anvil) via Homebrew
  • Scaffolded the repo with forge init
  • Wrote PiggyBank.sol: anyone deposits ETH, only the owner withdraws
  • Wrote 8 Foundry tests in Solidity, all passing, including a fuzz test that hit the contract with 256 random deposit amounts
  • Generated a fresh testnet-only wallet with cast wallet new
  • Spun up anvil (local chain, unlimited fake ETH) and deployed PiggyBank with forge create
  • Ran the full lifecycle from the terminal with cast: a stranger deposited 1 ETH, the stranger's withdrawal attempt reverted with NotOwner, the owner wallet withdrew everything

What I learned

  • msg.sender and msg.value: who is calling and how much ETH they attached
  • All amounts are in wei (1 ETH = 1e18 wei); there are no decimals on chain
  • payable, receive(), and why plain transfers revert without them
  • Modifiers as reusable access-control guards (onlyOwner)
  • Events are the contract's only output; indexers and dashboards live on them
  • Custom errors are cheaper than require strings and show up in traces
  • Send ETH with low-level call, not transfer (the 2300 gas stipend problem)
  • Fuzz testing: assert a property for all inputs, not one example
  • A deployed contract is forever; the rules at deploy time are the rules

Next up

  • Fund the testnet wallet from a Base Sepolia faucet
  • Deploy PiggyBank to Base Sepolia and verify it on a public explorer
  • Start project 2: write an ERC-20 token from scratch