Skip to content
Back

Blockchain Fundamentals: Wallets, Smart Contracts, Tokens, and dApps

Computer Science

A practical map of wallets, smart contracts, ERC token standards, and how dApps put them together

Most on-chain applications are built from the same handful of pieces: wallets, smart contracts, tokens, and dApps. Understanding how they connect — and what trust model each piece creates — is enough to read most Web3 architectures without drowning in cryptography.

This note uses an Ethereum / EVM framing because the ERC token standards live there. The same ideas transfer to other chains, even when the names change.



Blockchain Fundamentals

A blockchain is a shared ledger that many independent nodes agree on. Once a transaction is confirmed, rewriting history is expensive by design.

  • Accounts — identities on the chain. Externally owned accounts (EOAs) are controlled by private keys. Contract accounts are controlled by code.
  • Transactions — signed messages that propose a state change: send value, call a contract, deploy code.
  • Consensus — the network’s way of agreeing which transactions are valid and in what order.
  • Gas — the fee paid to execute work on-chain. Every write costs something; reads through an RPC node usually do not.

text
Signed transaction → Mempool → Included in a block → Shared state updated

The chain is a programmable settlement layer: slow and expensive compared with a normal database, but useful when ownership and rules must be publicly verifiable.



Wallets

A wallet is software (or hardware) that holds cryptographic keys and helps you sign transactions. It is not a bank account. The chain stores balances; the wallet stores the proof that you control an address.


text
Private key → Public key → Address
Private key -(signs)→ Transaction signature

  • A private key proves control. Anyone who has it can move assets from that address.
  • A public key / address is what others use to send you assets or identify you on-chain.
  • Signing means authorizing a specific transaction without broadcasting the private key itself.
  • Custody is who holds the keys. Self-custody means you hold them. Custodial wallets mean a service holds them on your behalf.
  • Browser extensions and mobile wallets are mainly UX around keys. Hardware wallets keep the private key offline and only expose signatures.

When a dApp says “connect wallet,” it is asking for an address and a signing channel — not for your password to a company database:


ts
const accounts = (await window.ethereum.request({
  method: "eth_requestAccounts",
})) as string[]

const address = accounts[0]
// address is public; the private key never leaves the wallet

Failure: treating “connect” as a Web2 login. Phishing sites ask you to sign the wrong thing, not to type a password.



Smart Contracts

A smart contract is a program deployed on the blockchain. On Ethereum it is usually written in Solidity and runs on the EVM. Once deployed, its code and storage live at a contract address.

  • Public state — anyone can read balances, ownership, and often the bytecode.
  • Deterministic execution — the same inputs and state produce the same result across honest nodes.
  • Permissionless calling — anyone who pays gas can call a public function, subject to the contract’s own access checks.
  • Hard to change — upgrades need an explicit pattern (proxy, governance, migration). There is no silent hotfix on immutable code.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract Escrow {
    address public payer;
    address public payee;
    bool public released;

    constructor(address _payee) payable {
        payer = msg.sender;
        payee = _payee;
    }

    function release() external {
        require(msg.sender == payer, "only payer");
        require(!released, "already released");
        released = true;
        payable(payee).transfer(address(this).balance);
    }
}

  • Contracts encode rules: who can call what, under which conditions, and what state changes.
  • A smart contract is an open, fee-metered API whose database is the chain. The UI can lie; the contract’s state is what actually settles.

Failure: treating the UI as the source of truth. Bugs are expensive because funds and ownership often sit inside the contract itself.



Tokens

Tokens are assets represented by smart contracts that follow shared interfaces. Wallets, explorers, and dApps can support them without custom code for every project — that is why ERC standards matter.

ERC-20 is the standard for fungible tokens: every unit is interchangeable. The mental model is balances, not unique items. approve + transferFrom is how a protocol spends tokens on your behalf.


solidity
interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

ERC-721 is the standard for unique tokens. Each tokenId is its own asset with a single owner. Collectibles, tickets, and on-chain deeds are common uses. Two tokens from the same contract are not interchangeable if their IDs differ.

ERC-1155 lets one contract manage many token types — fungible, non-fungible, or both — with batch transfers. Games and marketplaces often prefer it when a single collection mixes gold coins (fungible) with unique swords (supply of one) and limited skins (supply of N). Fewer deployments, cheaper batch operations.

StandardFungibilityIdentity modelCommon uses
ERC-20FungibleAmount per addressCurrencies, points, governance
ERC-721Non-fungibleOne owner per tokenIdCollectibles, tickets, unique rights
ERC-1155MixedBalance per address per idGames, multi-asset collections

All three are still just smart contracts. The ERC number is a shared interface so tooling can treat them consistently.



Decentralized Applications (dApps)

A dApp is an application whose critical logic or ownership lives on-chain.

  • A frontend (often a normal web app) for UX
  • A wallet for identity and transaction signing
  • Smart contracts as the source of truth for assets and rules
  • An RPC provider so the frontend can read chain state and broadcast signed transactions

text
User → Wallet
User → dApp Frontend
dApp Frontend -(read state)→ RPC Node
dApp Frontend -(request signature)→ Wallet
Wallet -(signed tx)→ RPC Node → Blockchain → Smart Contracts

  • Reads can be free and frequent. Writes require a signature and gas.
  • Many dApps still use centralized pieces — indexers, APIs, IPFS gateways, admin keys. “Decentralized” is a spectrum. What matters is which parts can fail or censor without taking away the user’s assets.


How They Fit Together

A concrete flow many products share:


text
User → dApp UI: Open app
dApp UI → Wallet: eth_requestAccounts
Wallet → dApp UI: address
dApp UI → Blockchain: balanceOf(address)
Blockchain → dApp UI: token balance
User → dApp UI: Deposit
dApp UI → Wallet: approve(protocol, amount)
Wallet → Blockchain: signed approve tx
dApp UI → Wallet: deposit(amount)
Wallet → Blockchain: signed deposit tx
Blockchain → dApp UI: updated state

  • User opens the dApp and connects a wallet. The app learns their address.
  • The UI reads balances and ownership through an RPC (balanceOf, ownerOf).
  • To deposit an ERC-20, they first approve the contract as a spender, then call deposit — two signatures, two transactions, unless batched by a higher-level pattern.
  • The smart contract updates on-chain state. The UI refreshes from the chain or an indexer.

ts
import { parseAbi, parseUnits } from "viem"

const amount = parseUnits("100", 6) // 100 USDC (6 decimals)

await walletClient.writeContract({
  address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  abi: parseAbi(["function approve(address spender, uint256 amount) returns (bool)"]),
  functionName: "approve",
  args: ["0xProtocolAddress", amount],
})

await walletClient.writeContract({
  address: "0xProtocolAddress",
  abi: parseAbi(["function deposit(uint256 amount)"]),
  functionName: "deposit",
  args: [amount],
})

Swap that ERC-20 for an ERC-721 mint, or an ERC-1155 batch claim, and the wallet / contract / RPC shape stays the same. Only the token interface and the contract’s business rules change.



Takeaways

  • A wallet holds keys, not the ledger itself — custody is about who can sign.
  • A smart contract is public, fee-metered logic whose state settles ownership.
  • ERC-20, ERC-721, and ERC-1155 differ mainly in fungibility and how identity is modeled.
  • A dApp combines frontend, wallet signatures, RPC, and contracts — the chain, not the UI, is the source of truth for assets.

Everything else — L2s, account abstraction, indexers, bridges — builds on this base.


Recap Q&A

Read the next note
Common Algorithms