{
  "version": "1",
  "access": "public-read-only",
  "lessonCount": 500,
  "toolExecution": "Tools execute in the browser; this API does not run tools or query a blockchain.",
  "lessons": [
    {
      "slug": "blockchain",
      "title": "What is a blockchain?",
      "summary": "A shared notebook that lots of computers check together.",
      "level": "beginner",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/blockchain/",
      "json": "https://ethertools.xyz/api/v1/lessons/blockchain.json",
      "markdown": "https://ethertools.xyz/markdown/learn/blockchain/index.md"
    },
    {
      "slug": "ethereum",
      "title": "What is Ethereum?",
      "summary": "A shared computer that anyone can use and anyone can check.",
      "level": "beginner",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/ethereum/",
      "json": "https://ethertools.xyz/api/v1/lessons/ethereum.json",
      "markdown": "https://ethertools.xyz/markdown/learn/ethereum/index.md"
    },
    {
      "slug": "digital-ledger",
      "title": "What is a digital ledger?",
      "summary": "A record of who owns what, or what changed, kept as data.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/digital-ledger/",
      "json": "https://ethertools.xyz/api/v1/lessons/digital-ledger.json",
      "markdown": "https://ethertools.xyz/markdown/learn/digital-ledger/index.md"
    },
    {
      "slug": "computers-agree",
      "title": "Why do computers need to agree?",
      "summary": "The order of valid updates can change the answer.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/computers-agree/",
      "json": "https://ethertools.xyz/api/v1/lessons/computers-agree.json",
      "markdown": "https://ethertools.xyz/markdown/learn/computers-agree/index.md"
    },
    {
      "slug": "block-anatomy",
      "title": "What makes a block a block?",
      "summary": "A batch of ordered transactions plus information needed to check it.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/block-anatomy/",
      "json": "https://ethertools.xyz/api/v1/lessons/block-anatomy.json",
      "markdown": "https://ethertools.xyz/markdown/learn/block-anatomy/index.md"
    },
    {
      "slug": "block-links",
      "title": "How are blocks linked?",
      "summary": "Each new block points to the fingerprint of its parent.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/block-links/",
      "json": "https://ethertools.xyz/api/v1/lessons/block-links.json",
      "markdown": "https://ethertools.xyz/markdown/learn/block-links/index.md"
    },
    {
      "slug": "transaction-intro",
      "title": "What is a transaction?",
      "summary": "An authorized instruction asking Ethereum to update its state.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/transaction-intro/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-intro.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-intro/index.md"
    },
    {
      "slug": "decentralization",
      "title": "What does decentralization mean?",
      "summary": "Control and verification are spread across participants.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/decentralization/",
      "json": "https://ethertools.xyz/api/v1/lessons/decentralization.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decentralization/index.md"
    },
    {
      "slug": "who-can-use-ethereum",
      "title": "Who can use Ethereum?",
      "summary": "The protocol is open, while individual services can set their own conditions.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/who-can-use-ethereum/",
      "json": "https://ethertools.xyz/api/v1/lessons/who-can-use-ethereum.json",
      "markdown": "https://ethertools.xyz/markdown/learn/who-can-use-ethereum/index.md"
    },
    {
      "slug": "who-owns-ethereum",
      "title": "Who owns Ethereum?",
      "summary": "No company owns the protocol in the way a company owns its private app.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/who-owns-ethereum/",
      "json": "https://ethertools.xyz/api/v1/lessons/who-owns-ethereum.json",
      "markdown": "https://ethertools.xyz/markdown/learn/who-owns-ethereum/index.md"
    },
    {
      "slug": "ethereum-and-internet",
      "title": "Ethereum versus the internet",
      "summary": "Ethereum uses the internet; it does not replace the whole thing.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/ethereum-and-internet/",
      "json": "https://ethertools.xyz/api/v1/lessons/ethereum-and-internet.json",
      "markdown": "https://ethertools.xyz/markdown/learn/ethereum-and-internet/index.md"
    },
    {
      "slug": "ethereum-and-bitcoin",
      "title": "Ethereum versus Bitcoin",
      "summary": "Two networks with different designs, assets and trade-offs.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/ethereum-and-bitcoin/",
      "json": "https://ethertools.xyz/api/v1/lessons/ethereum-and-bitcoin.json",
      "markdown": "https://ethertools.xyz/markdown/learn/ethereum-and-bitcoin/index.md"
    },
    {
      "slug": "blockchain-proofs",
      "title": "What can a blockchain prove?",
      "summary": "It can verify rule-following records, but external claims need extra trust.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/blockchain-proofs/",
      "json": "https://ethertools.xyz/api/v1/lessons/blockchain-proofs.json",
      "markdown": "https://ethertools.xyz/markdown/learn/blockchain-proofs/index.md"
    },
    {
      "slug": "blockchain-limits",
      "title": "What a blockchain cannot prove",
      "summary": "Correct execution does not make every input truthful or every outcome useful.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/blockchain-limits/",
      "json": "https://ethertools.xyz/api/v1/lessons/blockchain-limits.json",
      "markdown": "https://ethertools.xyz/markdown/learn/blockchain-limits/index.md"
    },
    {
      "slug": "public-not-anonymous",
      "title": "Public does not mean anonymous",
      "summary": "Addresses are pseudonyms, and public activity can reveal connections.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/public-not-anonymous/",
      "json": "https://ethertools.xyz/api/v1/lessons/public-not-anonymous.json",
      "markdown": "https://ethertools.xyz/markdown/learn/public-not-anonymous/index.md"
    },
    {
      "slug": "network-fee-intro",
      "title": "What is a network fee?",
      "summary": "A charge for the network resources used to process an action.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/network-fee-intro/",
      "json": "https://ethertools.xyz/api/v1/lessons/network-fee-intro.json",
      "markdown": "https://ethertools.xyz/markdown/learn/network-fee-intro/index.md"
    },
    {
      "slug": "account-intro",
      "title": "What is an Ethereum account?",
      "summary": "An entry in Ethereum’s state, identified by an address.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/account-intro/",
      "json": "https://ethertools.xyz/api/v1/lessons/account-intro.json",
      "markdown": "https://ethertools.xyz/markdown/learn/account-intro/index.md"
    },
    {
      "slug": "block-explorer-intro",
      "title": "Reading your first block explorer page",
      "summary": "Learn the labels before treating a receipt as a complete story.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/block-explorer-intro/",
      "json": "https://ethertools.xyz/api/v1/lessons/block-explorer-intro.json",
      "markdown": "https://ethertools.xyz/markdown/learn/block-explorer-intro/index.md"
    },
    {
      "slug": "ecosystem-tour",
      "title": "A tour of the Ethereum ecosystem",
      "summary": "The protocol, its interfaces and its applications form different layers.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/ecosystem-tour/",
      "json": "https://ethertools.xyz/api/v1/lessons/ecosystem-tour.json",
      "markdown": "https://ethertools.xyz/markdown/learn/ecosystem-tour/index.md"
    },
    {
      "slug": "blockchain-knowledge-check",
      "title": "Your first blockchain knowledge check",
      "summary": "Put the shared notebook, its rules and its limits together.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/blockchain-knowledge-check/",
      "json": "https://ethertools.xyz/api/v1/lessons/blockchain-knowledge-check.json",
      "markdown": "https://ethertools.xyz/markdown/learn/blockchain-knowledge-check/index.md"
    },
    {
      "slug": "ether-and-units",
      "title": "ETH, Gwei and Wei",
      "summary": "The same amount of ether, measured with different sized rulers.",
      "level": "beginner",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/ether-and-units/",
      "json": "https://ethertools.xyz/api/v1/lessons/ether-and-units.json",
      "markdown": "https://ethertools.xyz/markdown/learn/ether-and-units/index.md"
    },
    {
      "slug": "eth-versus-tokens",
      "title": "What makes ETH different from tokens?",
      "summary": "Native ETH is part of Ethereum’s accounting; a token follows its own contract.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/eth-versus-tokens/",
      "json": "https://ethertools.xyz/api/v1/lessons/eth-versus-tokens.json",
      "markdown": "https://ethertools.xyz/markdown/learn/eth-versus-tokens/index.md"
    },
    {
      "slug": "billion-and-quintillion",
      "title": "Count a billion and a quintillion",
      "summary": "Group the zeros before large Ethereum numbers become intimidating.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/billion-and-quintillion/",
      "json": "https://ethertools.xyz/api/v1/lessons/billion-and-quintillion.json",
      "markdown": "https://ethertools.xyz/markdown/learn/billion-and-quintillion/index.md"
    },
    {
      "slug": "eth-to-wei-by-hand",
      "title": "Convert ETH to Wei by hand",
      "summary": "Move the value into whole Wei without losing any decimal digits.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/eth-to-wei-by-hand/",
      "json": "https://ethertools.xyz/api/v1/lessons/eth-to-wei-by-hand.json",
      "markdown": "https://ethertools.xyz/markdown/learn/eth-to-wei-by-hand/index.md"
    },
    {
      "slug": "wei-to-eth-by-hand",
      "title": "Convert Wei to ETH by hand",
      "summary": "Divide a whole Wei amount by 10¹⁸ to display ether.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/wei-to-eth-by-hand/",
      "json": "https://ethertools.xyz/api/v1/lessons/wei-to-eth-by-hand.json",
      "markdown": "https://ethertools.xyz/markdown/learn/wei-to-eth-by-hand/index.md"
    },
    {
      "slug": "whole-number-amounts",
      "title": "Why Ethereum uses whole numbers",
      "summary": "Count the smallest units, then format them for people.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/whole-number-amounts/",
      "json": "https://ethertools.xyz/api/v1/lessons/whole-number-amounts.json",
      "markdown": "https://ethertools.xyz/markdown/learn/whole-number-amounts/index.md"
    },
    {
      "slug": "floating-point-amounts",
      "title": "Why floating-point amounts can fail",
      "summary": "Ordinary JavaScript numbers cannot preserve every possible Wei amount.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/floating-point-amounts/",
      "json": "https://ethertools.xyz/api/v1/lessons/floating-point-amounts.json",
      "markdown": "https://ethertools.xyz/markdown/learn/floating-point-amounts/index.md"
    },
    {
      "slug": "large-integer-reading",
      "title": "Read a very large integer",
      "summary": "Use groups and units to make long numbers legible without changing them.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/large-integer-reading/",
      "json": "https://ethertools.xyz/api/v1/lessons/large-integer-reading.json",
      "markdown": "https://ethertools.xyz/markdown/learn/large-integer-reading/index.md"
    },
    {
      "slug": "token-decimals",
      "title": "What are token decimals?",
      "summary": "A token’s display scale tells you where to place the decimal point.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/token-decimals/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-decimals.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-decimals/index.md"
    },
    {
      "slug": "display-and-raw-units",
      "title": "Display units versus raw units",
      "summary": "A friendly number and a machine integer can describe the same amount.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/display-and-raw-units/",
      "json": "https://ethertools.xyz/api/v1/lessons/display-and-raw-units.json",
      "markdown": "https://ethertools.xyz/markdown/learn/display-and-raw-units/index.md"
    },
    {
      "slug": "exact-amount-arithmetic",
      "title": "Add and subtract exact ETH amounts",
      "summary": "Convert to a common whole unit before combining amounts.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/exact-amount-arithmetic/",
      "json": "https://ethertools.xyz/api/v1/lessons/exact-amount-arithmetic.json",
      "markdown": "https://ethertools.xyz/markdown/learn/exact-amount-arithmetic/index.md"
    },
    {
      "slug": "rounding-and-truncation",
      "title": "Rounding versus truncation",
      "summary": "Discarding digits and choosing the nearest display value are different operations.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/rounding-and-truncation/",
      "json": "https://ethertools.xyz/api/v1/lessons/rounding-and-truncation.json",
      "markdown": "https://ethertools.xyz/markdown/learn/rounding-and-truncation/index.md"
    },
    {
      "slug": "converter-versus-price",
      "title": "Why a converter is not a price feed",
      "summary": "Unit conversion is fixed arithmetic; a market quote is changing external data.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/converter-versus-price/",
      "json": "https://ethertools.xyz/api/v1/lessons/converter-versus-price.json",
      "markdown": "https://ethertools.xyz/markdown/learn/converter-versus-price/index.md"
    },
    {
      "slug": "token-balance-meaning",
      "title": "What does a token balance mean?",
      "summary": "A number reported under a token contract’s rules, not a universal cash value.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/token-balance-meaning/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-balance-meaning.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-balance-meaning/index.md"
    },
    {
      "slug": "native-versus-token-transfer",
      "title": "Native transfers versus token transfers",
      "summary": "Sending ETH and asking a token contract to update balances use different fields.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/native-versus-token-transfer/",
      "json": "https://ethertools.xyz/api/v1/lessons/native-versus-token-transfer.json",
      "markdown": "https://ethertools.xyz/markdown/learn/native-versus-token-transfer/index.md"
    },
    {
      "slug": "total-and-circulating-supply",
      "title": "Total supply versus circulating supply",
      "summary": "Contract accounting and estimates of market availability answer different questions.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/total-and-circulating-supply/",
      "json": "https://ethertools.xyz/api/v1/lessons/total-and-circulating-supply.json",
      "markdown": "https://ethertools.xyz/markdown/learn/total-and-circulating-supply/index.md"
    },
    {
      "slug": "burning-explained",
      "title": "What does burning mean?",
      "summary": "The word can describe different mechanisms for removing assets from usable supply.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/burning-explained/",
      "json": "https://ethertools.xyz/api/v1/lessons/burning-explained.json",
      "markdown": "https://ethertools.xyz/markdown/learn/burning-explained/index.md"
    },
    {
      "slug": "minting-explained",
      "title": "What does minting mean?",
      "summary": "Creating units under a protocol or contract’s rules.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/minting-explained/",
      "json": "https://ethertools.xyz/api/v1/lessons/minting-explained.json",
      "markdown": "https://ethertools.xyz/markdown/learn/minting-explained/index.md"
    },
    {
      "slug": "dust-balances",
      "title": "Dust and very small balances",
      "summary": "A tiny amount can be exact even when moving it costs more than the amount itself.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/dust-balances/",
      "json": "https://ethertools.xyz/api/v1/lessons/dust-balances.json",
      "markdown": "https://ethertools.xyz/markdown/learn/dust-balances/index.md"
    },
    {
      "slug": "unit-conversion-practice",
      "title": "Unit conversion practice set",
      "summary": "Check the scale, preserve the integer, and verify your result.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/unit-conversion-practice/",
      "json": "https://ethertools.xyz/api/v1/lessons/unit-conversion-practice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/unit-conversion-practice/index.md"
    },
    {
      "slug": "wallets",
      "title": "Wallets, keys and addresses",
      "summary": "Your address receives things. Your keys authorize things.",
      "level": "beginner",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/wallets/",
      "json": "https://ethertools.xyz/api/v1/lessons/wallets.json",
      "markdown": "https://ethertools.xyz/markdown/learn/wallets/index.md"
    },
    {
      "slug": "wallet-stored-data",
      "title": "What a wallet actually stores",
      "summary": "The app manages access; the network records balances.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/wallet-stored-data/",
      "json": "https://ethertools.xyz/api/v1/lessons/wallet-stored-data.json",
      "markdown": "https://ethertools.xyz/markdown/learn/wallet-stored-data/index.md"
    },
    {
      "slug": "recovery-phrase",
      "title": "What is a recovery phrase?",
      "summary": "A human-readable secret that can restore key material for compatible wallets.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/recovery-phrase/",
      "json": "https://ethertools.xyz/api/v1/lessons/recovery-phrase.json",
      "markdown": "https://ethertools.xyz/markdown/learn/recovery-phrase/index.md"
    },
    {
      "slug": "public-and-private-keys",
      "title": "A public key versus a private key",
      "summary": "One secret authorizes; public information helps others verify.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/public-and-private-keys/",
      "json": "https://ethertools.xyz/api/v1/lessons/public-and-private-keys.json",
      "markdown": "https://ethertools.xyz/markdown/learn/public-and-private-keys/index.md"
    },
    {
      "slug": "address-not-username",
      "title": "A wallet address is not a username",
      "summary": "An address identifies an account, without a built-in password-reset desk.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/address-not-username/",
      "json": "https://ethertools.xyz/api/v1/lessons/address-not-username.json",
      "markdown": "https://ethertools.xyz/markdown/learn/address-not-username/index.md"
    },
    {
      "slug": "software-and-hardware-wallets",
      "title": "Software wallets and hardware wallets",
      "summary": "Different places to keep keys and perform signing, with different trade-offs.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/software-and-hardware-wallets/",
      "json": "https://ethertools.xyz/api/v1/lessons/software-and-hardware-wallets.json",
      "markdown": "https://ethertools.xyz/markdown/learn/software-and-hardware-wallets/index.md"
    },
    {
      "slug": "watch-only-wallets",
      "title": "Watch-only wallets",
      "summary": "A public view of an account without the power to sign for it.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/watch-only-wallets/",
      "json": "https://ethertools.xyz/api/v1/lessons/watch-only-wallets.json",
      "markdown": "https://ethertools.xyz/markdown/learn/watch-only-wallets/index.md"
    },
    {
      "slug": "one-phrase-many-accounts",
      "title": "One recovery phrase, many accounts",
      "summary": "A deterministic key tree can produce several account identities.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/one-phrase-many-accounts/",
      "json": "https://ethertools.xyz/api/v1/lessons/one-phrase-many-accounts.json",
      "markdown": "https://ethertools.xyz/markdown/learn/one-phrase-many-accounts/index.md"
    },
    {
      "slug": "derivation-paths",
      "title": "What is a derivation path?",
      "summary": "A set of instructions for choosing a branch in a deterministic key tree.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/derivation-paths/",
      "json": "https://ethertools.xyz/api/v1/lessons/derivation-paths.json",
      "markdown": "https://ethertools.xyz/markdown/learn/derivation-paths/index.md"
    },
    {
      "slug": "contract-wallets",
      "title": "What is a contract wallet?",
      "summary": "An account whose authorization rules can be implemented through code.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-wallets/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-wallets.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-wallets/index.md"
    },
    {
      "slug": "multisignature-wallets",
      "title": "What is a multisignature wallet?",
      "summary": "A policy requiring several approvals before an action is allowed.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/multisignature-wallets/",
      "json": "https://ethertools.xyz/api/v1/lessons/multisignature-wallets.json",
      "markdown": "https://ethertools.xyz/markdown/learn/multisignature-wallets/index.md"
    },
    {
      "slug": "wallet-connection-permissions",
      "title": "What does connecting a wallet allow?",
      "summary": "Connection is one permission step; signing and spending authorization are separate.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/wallet-connection-permissions/",
      "json": "https://ethertools.xyz/api/v1/lessons/wallet-connection-permissions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/wallet-connection-permissions/index.md"
    },
    {
      "slug": "disconnecting-and-revoking",
      "title": "Disconnecting is not revoking approval",
      "summary": "A website connection and an onchain allowance live in different places.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/disconnecting-and-revoking/",
      "json": "https://ethertools.xyz/api/v1/lessons/disconnecting-and-revoking.json",
      "markdown": "https://ethertools.xyz/markdown/learn/disconnecting-and-revoking/index.md"
    },
    {
      "slug": "wallet-networks",
      "title": "What are wallet networks?",
      "summary": "A wallet can connect to different chains, each with its own state.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/wallet-networks/",
      "json": "https://ethertools.xyz/api/v1/lessons/wallet-networks.json",
      "markdown": "https://ethertools.xyz/markdown/learn/wallet-networks/index.md"
    },
    {
      "slug": "balances-across-networks",
      "title": "Why balances differ across networks",
      "summary": "Matching address text does not mean shared account state.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/balances-across-networks/",
      "json": "https://ethertools.xyz/api/v1/lessons/balances-across-networks.json",
      "markdown": "https://ethertools.xyz/markdown/learn/balances-across-networks/index.md"
    },
    {
      "slug": "wallet-confirmation-screen",
      "title": "Read a wallet confirmation screen",
      "summary": "Check what you authorize, including details a friendly button can hide.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/wallet-confirmation-screen/",
      "json": "https://ethertools.xyz/api/v1/lessons/wallet-confirmation-screen.json",
      "markdown": "https://ethertools.xyz/markdown/learn/wallet-confirmation-screen/index.md"
    },
    {
      "slug": "receive-screen",
      "title": "Understand a receive screen",
      "summary": "A receiving address is useful only with the right network and asset context.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/receive-screen/",
      "json": "https://ethertools.xyz/api/v1/lessons/receive-screen.json",
      "markdown": "https://ethertools.xyz/markdown/learn/receive-screen/index.md"
    },
    {
      "slug": "copy-addresses",
      "title": "Copy addresses without shortcuts",
      "summary": "Compare the full destination and its context, not just a short prefix.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/copy-addresses/",
      "json": "https://ethertools.xyz/api/v1/lessons/copy-addresses.json",
      "markdown": "https://ethertools.xyz/markdown/learn/copy-addresses/index.md"
    },
    {
      "slug": "backup-recovery-basics",
      "title": "Backups and recovery basics",
      "summary": "Understand the exact recovery ingredients before a device is lost.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/backup-recovery-basics/",
      "json": "https://ethertools.xyz/api/v1/lessons/backup-recovery-basics.json",
      "markdown": "https://ethertools.xyz/markdown/learn/backup-recovery-basics/index.md"
    },
    {
      "slug": "wallet-safety-check",
      "title": "Wallet safety knowledge check",
      "summary": "Put account access, networks and permissions into one simple review.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/wallet-safety-check/",
      "json": "https://ethertools.xyz/api/v1/lessons/wallet-safety-check.json",
      "markdown": "https://ethertools.xyz/markdown/learn/wallet-safety-check/index.md"
    },
    {
      "slug": "security",
      "title": "Stay safe while exploring",
      "summary": "Build good habits before you connect a real wallet.",
      "level": "beginner",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/security/",
      "json": "https://ethertools.xyz/api/v1/lessons/security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/security/index.md"
    },
    {
      "slug": "fake-support",
      "title": "Spot a fake support message",
      "summary": "A helpful tone is not proof of authority.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/fake-support/",
      "json": "https://ethertools.xyz/api/v1/lessons/fake-support.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fake-support/index.md"
    },
    {
      "slug": "phrase-scam",
      "title": "Recognize a recovery phrase scam",
      "summary": "A request for the master backup is a request for control.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/phrase-scam/",
      "json": "https://ethertools.xyz/api/v1/lessons/phrase-scam.json",
      "markdown": "https://ethertools.xyz/markdown/learn/phrase-scam/index.md"
    },
    {
      "slug": "address-poisoning",
      "title": "Address poisoning explained",
      "summary": "A lookalike address can be planted where you expect useful history.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/address-poisoning/",
      "json": "https://ethertools.xyz/api/v1/lessons/address-poisoning.json",
      "markdown": "https://ethertools.xyz/markdown/learn/address-poisoning/index.md"
    },
    {
      "slug": "clipboard-attacks",
      "title": "Clipboard replacement attacks",
      "summary": "Check the destination after pasting, not only before copying.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/clipboard-attacks/",
      "json": "https://ethertools.xyz/api/v1/lessons/clipboard-attacks.json",
      "markdown": "https://ethertools.xyz/markdown/learn/clipboard-attacks/index.md"
    },
    {
      "slug": "read-domain",
      "title": "Read a domain carefully",
      "summary": "A familiar brand name inside a URL is not enough.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/read-domain/",
      "json": "https://ethertools.xyz/api/v1/lessons/read-domain.json",
      "markdown": "https://ethertools.xyz/markdown/learn/read-domain/index.md"
    },
    {
      "slug": "token-approval-basics",
      "title": "Understand token approvals",
      "summary": "An allowance lets a specified spender request token movement under contract rules.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/token-approval-basics/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-approval-basics.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-approval-basics/index.md"
    },
    {
      "slug": "unlimited-allowances",
      "title": "Unlimited allowances explained",
      "summary": "A very large spending permission can expose more than the next intended payment.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/unlimited-allowances/",
      "json": "https://ethertools.xyz/api/v1/lessons/unlimited-allowances.json",
      "markdown": "https://ethertools.xyz/markdown/learn/unlimited-allowances/index.md"
    },
    {
      "slug": "malicious-signatures",
      "title": "What is a malicious signature?",
      "summary": "A valid signature can authorize an action the signer did not intend.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/malicious-signatures/",
      "json": "https://ethertools.xyz/api/v1/lessons/malicious-signatures.json",
      "markdown": "https://ethertools.xyz/markdown/learn/malicious-signatures/index.md"
    },
    {
      "slug": "airdrop-bait",
      "title": "Why an airdrop can be bait",
      "summary": "An unsolicited asset can be used to lure someone into a separate harmful action.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/airdrop-bait/",
      "json": "https://ethertools.xyz/api/v1/lessons/airdrop-bait.json",
      "markdown": "https://ethertools.xyz/markdown/learn/airdrop-bait/index.md"
    },
    {
      "slug": "testnet-purpose",
      "title": "What a testnet is for",
      "summary": "A separate network lets people practice protocol and application behavior.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/testnet-purpose/",
      "json": "https://ethertools.xyz/api/v1/lessons/testnet-purpose.json",
      "markdown": "https://ethertools.xyz/markdown/learn/testnet-purpose/index.md"
    },
    {
      "slug": "test-eth",
      "title": "Test ETH versus real ETH",
      "summary": "The same unit names do not make separate networks’ assets interchangeable.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/test-eth/",
      "json": "https://ethertools.xyz/api/v1/lessons/test-eth.json",
      "markdown": "https://ethertools.xyz/markdown/learn/test-eth/index.md"
    },
    {
      "slug": "faucet-warnings",
      "title": "How to read a faucet warning",
      "summary": "Separate a legitimate service condition from a request for secret access.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/faucet-warnings/",
      "json": "https://ethertools.xyz/api/v1/lessons/faucet-warnings.json",
      "markdown": "https://ethertools.xyz/markdown/learn/faucet-warnings/index.md"
    },
    {
      "slug": "verify-address-channels",
      "title": "Verify an address through two channels",
      "summary": "Independent confirmation can catch a changed or impersonated destination.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/verify-address-channels/",
      "json": "https://ethertools.xyz/api/v1/lessons/verify-address-channels.json",
      "markdown": "https://ethertools.xyz/markdown/learn/verify-address-channels/index.md"
    },
    {
      "slug": "irreversible-transactions",
      "title": "Why transactions are usually irreversible",
      "summary": "Accepted state changes do not have a universal user-operated undo button.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/irreversible-transactions/",
      "json": "https://ethertools.xyz/api/v1/lessons/irreversible-transactions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/irreversible-transactions/index.md"
    },
    {
      "slug": "explorer-label-limits",
      "title": "What a block explorer label does not prove",
      "summary": "Human-friendly tags are interpretations layered onto network data.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/explorer-label-limits/",
      "json": "https://ethertools.xyz/api/v1/lessons/explorer-label-limits.json",
      "markdown": "https://ethertools.xyz/markdown/learn/explorer-label-limits/index.md"
    },
    {
      "slug": "hardware-review",
      "title": "Hardware wallets still need careful review",
      "summary": "Protecting a key does not automatically explain a request’s meaning.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/hardware-review/",
      "json": "https://ethertools.xyz/api/v1/lessons/hardware-review.json",
      "markdown": "https://ethertools.xyz/markdown/learn/hardware-review/index.md"
    },
    {
      "slug": "read-only-practice",
      "title": "Read-only practice habits",
      "summary": "Learn byte shapes and public data before authorizing real actions.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/read-only-practice/",
      "json": "https://ethertools.xyz/api/v1/lessons/read-only-practice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/read-only-practice/index.md"
    },
    {
      "slug": "personal-transaction-checklist",
      "title": "Prepare a personal transaction checklist",
      "summary": "A short review can keep different kinds of evidence from being mixed up.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/personal-transaction-checklist/",
      "json": "https://ethertools.xyz/api/v1/lessons/personal-transaction-checklist.json",
      "markdown": "https://ethertools.xyz/markdown/learn/personal-transaction-checklist/index.md"
    },
    {
      "slug": "safety-scenario-challenge",
      "title": "Safety scenario challenge",
      "summary": "Practice identifying what a request actually grants.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/safety-scenario-challenge/",
      "json": "https://ethertools.xyz/api/v1/lessons/safety-scenario-challenge.json",
      "markdown": "https://ethertools.xyz/markdown/learn/safety-scenario-challenge/index.md"
    },
    {
      "slug": "transactions",
      "title": "Follow a transaction",
      "summary": "From pressing send to becoming part of the shared history.",
      "level": "beginner",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/transactions/",
      "json": "https://ethertools.xyz/api/v1/lessons/transactions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transactions/index.md"
    },
    {
      "slug": "payment-instruction",
      "title": "Write a payment instruction",
      "summary": "An amount needs a destination, network and authorization context.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/payment-instruction/",
      "json": "https://ethertools.xyz/api/v1/lessons/payment-instruction.json",
      "markdown": "https://ethertools.xyz/markdown/learn/payment-instruction/index.md"
    },
    {
      "slug": "transaction-hash",
      "title": "What is a transaction hash?",
      "summary": "A fingerprint identifies encoded transaction data; it is not a success certificate.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-hash/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-hash.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-hash/index.md"
    },
    {
      "slug": "transaction-nonce",
      "title": "What is a nonce?",
      "summary": "An account’s transaction sequence helps keep instructions in order.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-nonce/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-nonce.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-nonce/index.md"
    },
    {
      "slug": "transaction-status",
      "title": "Pending, confirmed and finalized",
      "summary": "Different stages answer different questions about a transaction.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-status/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-status.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-status/index.md"
    },
    {
      "slug": "mempool",
      "title": "What is a mempool?",
      "summary": "A node’s local collection of pending transaction candidates.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/mempool/",
      "json": "https://ethertools.xyz/api/v1/lessons/mempool.json",
      "markdown": "https://ethertools.xyz/markdown/learn/mempool/index.md"
    },
    {
      "slug": "transaction-inclusion",
      "title": "Who includes a transaction?",
      "summary": "A block proposal chooses candidate transactions, while nodes verify the result.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-inclusion/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-inclusion.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-inclusion/index.md"
    },
    {
      "slug": "pending-delays",
      "title": "Why a transaction may wait",
      "summary": "Fee conditions, nonce gaps and propagation can all delay inclusion.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/pending-delays/",
      "json": "https://ethertools.xyz/api/v1/lessons/pending-delays.json",
      "markdown": "https://ethertools.xyz/markdown/learn/pending-delays/index.md"
    },
    {
      "slug": "transaction-failures",
      "title": "Why a transaction may fail",
      "summary": "Rejection before inclusion differs from a revert during execution.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-failures/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-failures.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-failures/index.md"
    },
    {
      "slug": "transaction-receipt",
      "title": "What is a transaction receipt?",
      "summary": "A result record for a transaction included in a block.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-receipt/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-receipt.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-receipt/index.md"
    },
    {
      "slug": "gas-used-and-limit",
      "title": "Gas used versus gas limit",
      "summary": "A ceiling on work is different from the work actually consumed.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/gas-used-and-limit/",
      "json": "https://ethertools.xyz/api/v1/lessons/gas-used-and-limit.json",
      "markdown": "https://ethertools.xyz/markdown/learn/gas-used-and-limit/index.md"
    },
    {
      "slug": "sender-and-recipient",
      "title": "The recipient versus the sender",
      "summary": "Who authorizes a transaction can differ from who receives an asset.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/sender-and-recipient/",
      "json": "https://ethertools.xyz/api/v1/lessons/sender-and-recipient.json",
      "markdown": "https://ethertools.xyz/markdown/learn/sender-and-recipient/index.md"
    },
    {
      "slug": "transaction-value-and-fee",
      "title": "Transaction value versus fee",
      "summary": "The native amount sent and the cost of execution are separate.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-value-and-fee/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-value-and-fee.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-value-and-fee/index.md"
    },
    {
      "slug": "read-transfer-receipt",
      "title": "Read a simple transfer receipt",
      "summary": "Use a fictional receipt to connect status, gas and block context.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/read-transfer-receipt/",
      "json": "https://ethertools.xyz/api/v1/lessons/read-transfer-receipt.json",
      "markdown": "https://ethertools.xyz/markdown/learn/read-transfer-receipt/index.md"
    },
    {
      "slug": "after-pressing-send",
      "title": "What happens after pressing send?",
      "summary": "A wallet action begins a process with several observable stages.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/after-pressing-send/",
      "json": "https://ethertools.xyz/api/v1/lessons/after-pressing-send.json",
      "markdown": "https://ethertools.xyz/markdown/learn/after-pressing-send/index.md"
    },
    {
      "slug": "replacement-transactions",
      "title": "What is a replacement transaction?",
      "summary": "A competing instruction can target the same sender nonce.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/replacement-transactions/",
      "json": "https://ethertools.xyz/api/v1/lessons/replacement-transactions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/replacement-transactions/index.md"
    },
    {
      "slug": "canceling-transactions",
      "title": "What does canceling a transaction mean?",
      "summary": "A wallet’s cancel action often submits a competing request; it is not an undo switch.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/canceling-transactions/",
      "json": "https://ethertools.xyz/api/v1/lessons/canceling-transactions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/canceling-transactions/index.md"
    },
    {
      "slug": "chain-reorganizations",
      "title": "What is a chain reorganization?",
      "summary": "A node can replace its view of recent unfinalized blocks with another valid branch.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/chain-reorganizations/",
      "json": "https://ethertools.xyz/api/v1/lessons/chain-reorganizations.json",
      "markdown": "https://ethertools.xyz/markdown/learn/chain-reorganizations/index.md"
    },
    {
      "slug": "transaction-journey-illustrated",
      "title": "A transaction journey illustrated",
      "summary": "Connect the full sequence through one fictional payment.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-journey-illustrated/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-journey-illustrated.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-journey-illustrated/index.md"
    },
    {
      "slug": "transaction-basics-check",
      "title": "Transaction basics knowledge check",
      "summary": "Use the right evidence for ordering, cost, execution and settlement.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-basics-check/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-basics-check.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-basics-check/index.md"
    },
    {
      "slug": "smart-contracts",
      "title": "Smart contracts, simply",
      "summary": "Programs that apply rules on Ethereum.",
      "level": "beginner",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/smart-contracts/",
      "json": "https://ethertools.xyz/api/v1/lessons/smart-contracts.json",
      "markdown": "https://ethertools.xyz/markdown/learn/smart-contracts/index.md"
    },
    {
      "slug": "counter-contract",
      "title": "A counter as a contract",
      "summary": "A small state variable and one rule make execution easier to picture.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/counter-contract/",
      "json": "https://ethertools.xyz/api/v1/lessons/counter-contract.json",
      "markdown": "https://ethertools.xyz/markdown/learn/counter-contract/index.md"
    },
    {
      "slug": "function-arguments",
      "title": "Functions and arguments explained",
      "summary": "A function identifies an action; arguments supply the details.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/function-arguments/",
      "json": "https://ethertools.xyz/api/v1/lessons/function-arguments.json",
      "markdown": "https://ethertools.xyz/markdown/learn/function-arguments/index.md"
    },
    {
      "slug": "reads-and-writes",
      "title": "Reading a contract versus changing it",
      "summary": "A local read can simulate execution; persistent updates need accepted transaction processing.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/reads-and-writes/",
      "json": "https://ethertools.xyz/api/v1/lessons/reads-and-writes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/reads-and-writes/index.md"
    },
    {
      "slug": "contract-state",
      "title": "What does contract state mean?",
      "summary": "The values a contract currently remembers after accepted updates.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-state/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-state.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-state/index.md"
    },
    {
      "slug": "contract-callers",
      "title": "Who can call a smart contract?",
      "summary": "Reachability and permission are different questions.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-callers/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-callers.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-callers/index.md"
    },
    {
      "slug": "contract-address",
      "title": "A contract has an address too",
      "summary": "An address can identify code and its state, not only a key-controlled account.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-address/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-address.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-address/index.md"
    },
    {
      "slug": "contract-deployment",
      "title": "What is deployment?",
      "summary": "Creation execution can install runtime code at a new contract address.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-deployment/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-deployment.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-deployment/index.md"
    },
    {
      "slug": "contract-bytecode",
      "title": "What is contract bytecode?",
      "summary": "Machine-readable instructions differ from human-readable Solidity.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-bytecode/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-bytecode.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-bytecode/index.md"
    },
    {
      "slug": "verified-source",
      "title": "What is verified source code?",
      "summary": "A source match helps inspection but does not certify safe behavior.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/verified-source/",
      "json": "https://ethertools.xyz/api/v1/lessons/verified-source.json",
      "markdown": "https://ethertools.xyz/markdown/learn/verified-source/index.md"
    },
    {
      "slug": "abi-description",
      "title": "What an ABI describes",
      "summary": "The interface tells software how to format requests and results.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/abi-description/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-description.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-description/index.md"
    },
    {
      "slug": "contract-limits",
      "title": "What contracts cannot do alone",
      "summary": "Deterministic execution needs explicit inputs and a trigger.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-limits/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-limits.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-limits/index.md"
    },
    {
      "slug": "oracle-intro",
      "title": "What is an oracle?",
      "summary": "A mechanism for supplying information a contract cannot directly observe.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/oracle-intro/",
      "json": "https://ethertools.xyz/api/v1/lessons/oracle-intro.json",
      "markdown": "https://ethertools.xyz/markdown/learn/oracle-intro/index.md"
    },
    {
      "slug": "permission-checks",
      "title": "What is a permission check?",
      "summary": "A rule determines whether the current caller may perform an action.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/permission-checks/",
      "json": "https://ethertools.xyz/api/v1/lessons/permission-checks.json",
      "markdown": "https://ethertools.xyz/markdown/learn/permission-checks/index.md"
    },
    {
      "slug": "administrator-keys",
      "title": "What is an administrator key?",
      "summary": "Some systems give an account special powers over configuration or upgrades.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/administrator-keys/",
      "json": "https://ethertools.xyz/api/v1/lessons/administrator-keys.json",
      "markdown": "https://ethertools.xyz/markdown/learn/administrator-keys/index.md"
    },
    {
      "slug": "contract-upgrades",
      "title": "Can a contract be upgraded?",
      "summary": "Some application designs can change behavior through explicit upgrade mechanisms.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-upgrades/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-upgrades.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-upgrades/index.md"
    },
    {
      "slug": "contract-bug-costs",
      "title": "Why bugs can be expensive",
      "summary": "Public execution can apply an unintended rule just as faithfully as an intended one.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-bug-costs/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-bug-costs.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-bug-costs/index.md"
    },
    {
      "slug": "vending-machine-analogy",
      "title": "A vending machine analogy and its limits",
      "summary": "An everyday comparison is useful only while its boundaries remain clear.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/vending-machine-analogy/",
      "json": "https://ethertools.xyz/api/v1/lessons/vending-machine-analogy.json",
      "markdown": "https://ethertools.xyz/markdown/learn/vending-machine-analogy/index.md"
    },
    {
      "slug": "pretend-contract-call",
      "title": "Walk through a pretend contract call",
      "summary": "Follow one input from the interface to its checked state update.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/pretend-contract-call/",
      "json": "https://ethertools.xyz/api/v1/lessons/pretend-contract-call.json",
      "markdown": "https://ethertools.xyz/markdown/learn/pretend-contract-call/index.md"
    },
    {
      "slug": "contract-basics-check",
      "title": "Smart contract knowledge check",
      "summary": "Connect interfaces, execution, persistent state and trust boundaries.",
      "level": "beginner",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/contract-basics-check/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-basics-check.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-basics-check/index.md"
    },
    {
      "slug": "tokens",
      "title": "Tokens, NFTs and allowances",
      "summary": "Contracts keep ownership records; standards make them easier to use.",
      "level": "intermediate",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/tokens/",
      "json": "https://ethertools.xyz/api/v1/lessons/tokens.json",
      "markdown": "https://ethertools.xyz/markdown/learn/tokens/index.md"
    },
    {
      "slug": "erc20-balance-records",
      "title": "How ERC-20 balances are recorded",
      "summary": "A token contract defines how an account’s quantity is represented.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/erc20-balance-records/",
      "json": "https://ethertools.xyz/api/v1/lessons/erc20-balance-records.json",
      "markdown": "https://ethertools.xyz/markdown/learn/erc20-balance-records/index.md"
    },
    {
      "slug": "transfer-and-transferfrom",
      "title": "Understand transfer and transferFrom",
      "summary": "Moving your own tokens and spending with permission use different interfaces.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transfer-and-transferfrom/",
      "json": "https://ethertools.xyz/api/v1/lessons/transfer-and-transferfrom.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transfer-and-transferfrom/index.md"
    },
    {
      "slug": "read-allowance",
      "title": "Read an allowance",
      "summary": "Identify the owner, spender, token and network behind the number.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/read-allowance/",
      "json": "https://ethertools.xyz/api/v1/lessons/read-allowance.json",
      "markdown": "https://ethertools.xyz/markdown/learn/read-allowance/index.md"
    },
    {
      "slug": "allowance-changes",
      "title": "Approve zero and allowance changes",
      "summary": "Changing a standing permission requires attention to ordering.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/allowance-changes/",
      "json": "https://ethertools.xyz/api/v1/lessons/allowance-changes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/allowance-changes/index.md"
    },
    {
      "slug": "erc20-decimals-convention",
      "title": "The ERC-20 decimals convention",
      "summary": "A metadata method helps applications format a raw token integer.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/erc20-decimals-convention/",
      "json": "https://ethertools.xyz/api/v1/lessons/erc20-decimals-convention.json",
      "markdown": "https://ethertools.xyz/markdown/learn/erc20-decimals-convention/index.md"
    },
    {
      "slug": "nft-uniqueness",
      "title": "What makes an NFT unique?",
      "summary": "A token ID distinguishes an item within its contract’s collection.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/nft-uniqueness/",
      "json": "https://ethertools.xyz/api/v1/lessons/nft-uniqueness.json",
      "markdown": "https://ethertools.xyz/markdown/learn/nft-uniqueness/index.md"
    },
    {
      "slug": "erc721-ownership",
      "title": "ERC-721 ownership and token IDs",
      "summary": "A standard ownership query names one individually tracked token.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/erc721-ownership/",
      "json": "https://ethertools.xyz/api/v1/lessons/erc721-ownership.json",
      "markdown": "https://ethertools.xyz/markdown/learn/erc721-ownership/index.md"
    },
    {
      "slug": "erc1155-types",
      "title": "ERC-1155 multiple token types",
      "summary": "One contract can manage balances for several item IDs.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/erc1155-types/",
      "json": "https://ethertools.xyz/api/v1/lessons/erc1155-types.json",
      "markdown": "https://ethertools.xyz/markdown/learn/erc1155-types/index.md"
    },
    {
      "slug": "metadata-and-ownership",
      "title": "Metadata and token ownership differ",
      "summary": "A token’s owner record and its descriptive data are separate claims.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/metadata-and-ownership/",
      "json": "https://ethertools.xyz/api/v1/lessons/metadata-and-ownership.json",
      "markdown": "https://ethertools.xyz/markdown/learn/metadata-and-ownership/index.md"
    },
    {
      "slug": "nft-image-storage",
      "title": "Where NFT images can live",
      "summary": "The token may point to media hosted somewhere else.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/nft-image-storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/nft-image-storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/nft-image-storage/index.md"
    },
    {
      "slug": "onchain-offchain-metadata",
      "title": "Onchain versus offchain metadata",
      "summary": "Find which parts of a description depend on the chain and which depend on another service.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/onchain-offchain-metadata/",
      "json": "https://ethertools.xyz/api/v1/lessons/onchain-offchain-metadata.json",
      "markdown": "https://ethertools.xyz/markdown/learn/onchain-offchain-metadata/index.md"
    },
    {
      "slug": "token-standard-guarantees",
      "title": "What does a token standard guarantee?",
      "summary": "An interface specification supports interoperability, not universal safety.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/token-standard-guarantees/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-standard-guarantees.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-standard-guarantees/index.md"
    },
    {
      "slug": "token-name-identity",
      "title": "Why token names are not identities",
      "summary": "Names and symbols can be reused by unrelated contracts.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/token-name-identity/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-name-identity.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-name-identity/index.md"
    },
    {
      "slug": "wrapped-eth",
      "title": "Wrapped ETH explained",
      "summary": "A contract representation can make ETH usable through a token-style interface.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/wrapped-eth/",
      "json": "https://ethertools.xyz/api/v1/lessons/wrapped-eth.json",
      "markdown": "https://ethertools.xyz/markdown/learn/wrapped-eth/index.md"
    },
    {
      "slug": "stablecoin-mechanisms",
      "title": "Stablecoin mechanisms at a glance",
      "summary": "A target price depends on a design, not on the word stable.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/stablecoin-mechanisms/",
      "json": "https://ethertools.xyz/api/v1/lessons/stablecoin-mechanisms.json",
      "markdown": "https://ethertools.xyz/markdown/learn/stablecoin-mechanisms/index.md"
    },
    {
      "slug": "rebasing-tokens",
      "title": "Rebasing tokens explained",
      "summary": "A balance can change through a supply-adjustment mechanism rather than an ordinary transfer.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/rebasing-tokens/",
      "json": "https://ethertools.xyz/api/v1/lessons/rebasing-tokens.json",
      "markdown": "https://ethertools.xyz/markdown/learn/rebasing-tokens/index.md"
    },
    {
      "slug": "fee-on-transfer",
      "title": "Fee-on-transfer tokens explained",
      "summary": "The requested amount and the recipient’s net increase can differ.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/fee-on-transfer/",
      "json": "https://ethertools.xyz/api/v1/lessons/fee-on-transfer.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fee-on-transfer/index.md"
    },
    {
      "slug": "token-events-behavior",
      "title": "Events versus actual token behavior",
      "summary": "A log is a record emitted by code, not a universal guarantee of balance movement.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/token-events-behavior/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-events-behavior.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-events-behavior/index.md"
    },
    {
      "slug": "token-interface-practice",
      "title": "Token interface practice set",
      "summary": "Distinguish identity, amounts, permissions and event layouts.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/token-interface-practice/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-interface-practice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-interface-practice/index.md"
    },
    {
      "slug": "gas",
      "title": "Gas without the guesswork",
      "summary": "Gas measures work. A gas price tells you what that work costs.",
      "level": "intermediate",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/gas/",
      "json": "https://ethertools.xyz/api/v1/lessons/gas.json",
      "markdown": "https://ethertools.xyz/markdown/learn/gas/index.md"
    },
    {
      "slug": "gas-work",
      "title": "Gas as a measure of work",
      "summary": "Resource accounting and the price of that resource are separate quantities.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/gas-work/",
      "json": "https://ethertools.xyz/api/v1/lessons/gas-work.json",
      "markdown": "https://ethertools.xyz/markdown/learn/gas-work/index.md"
    },
    {
      "slug": "simple-transfer-gas",
      "title": "The 21,000 gas transfer example",
      "summary": "A narrow simple case is useful without being a universal transfer estimate.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/simple-transfer-gas/",
      "json": "https://ethertools.xyz/api/v1/lessons/simple-transfer-gas.json",
      "markdown": "https://ethertools.xyz/markdown/learn/simple-transfer-gas/index.md"
    },
    {
      "slug": "transaction-and-block-gas",
      "title": "Gas limit versus block gas limit",
      "summary": "A transaction budget and a block’s resource constraint apply at different scopes.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/transaction-and-block-gas/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-and-block-gas.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-and-block-gas/index.md"
    },
    {
      "slug": "eip1559-simple",
      "title": "EIP-1559 in plain language",
      "summary": "A block base fee and transaction fee caps replace a single-price mental model.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/eip1559-simple/",
      "json": "https://ethertools.xyz/api/v1/lessons/eip1559-simple.json",
      "markdown": "https://ethertools.xyz/markdown/learn/eip1559-simple/index.md"
    },
    {
      "slug": "base-fee",
      "title": "Base fee explained",
      "summary": "A protocol-determined per-gas component changes with block demand under specified rules.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/base-fee/",
      "json": "https://ethertools.xyz/api/v1/lessons/base-fee.json",
      "markdown": "https://ethertools.xyz/markdown/learn/base-fee/index.md"
    },
    {
      "slug": "priority-fee",
      "title": "Priority fee explained",
      "summary": "The effective tip can be lower than the requested priority cap.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/priority-fee/",
      "json": "https://ethertools.xyz/api/v1/lessons/priority-fee.json",
      "markdown": "https://ethertools.xyz/markdown/learn/priority-fee/index.md"
    },
    {
      "slug": "max-fee-cap",
      "title": "Maximum fee cap explained",
      "summary": "The maximum per-gas rate sets a ceiling, not a fixed quote.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/max-fee-cap/",
      "json": "https://ethertools.xyz/api/v1/lessons/max-fee-cap.json",
      "markdown": "https://ethertools.xyz/markdown/learn/max-fee-cap/index.md"
    },
    {
      "slug": "effective-gas-price",
      "title": "Calculate the effective gas price",
      "summary": "Apply both caps after checking that base fee is covered.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/effective-gas-price/",
      "json": "https://ethertools.xyz/api/v1/lessons/effective-gas-price.json",
      "markdown": "https://ethertools.xyz/markdown/learn/effective-gas-price/index.md"
    },
    {
      "slug": "unused-gas",
      "title": "What happens to unused gas?",
      "summary": "A gas limit is a permitted ceiling rather than a requirement to consume it.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/unused-gas/",
      "json": "https://ethertools.xyz/api/v1/lessons/unused-gas.json",
      "markdown": "https://ethertools.xyz/markdown/learn/unused-gas/index.md"
    },
    {
      "slug": "out-of-gas",
      "title": "What happens when gas runs out?",
      "summary": "Execution cannot keep working after exhausting its permitted resources.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/out-of-gas/",
      "json": "https://ethertools.xyz/api/v1/lessons/out-of-gas.json",
      "markdown": "https://ethertools.xyz/markdown/learn/out-of-gas/index.md"
    },
    {
      "slug": "revert-gas-cost",
      "title": "Why a revert still costs gas",
      "summary": "Rolling back state does not erase computation already performed.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/revert-gas-cost/",
      "json": "https://ethertools.xyz/api/v1/lessons/revert-gas-cost.json",
      "markdown": "https://ethertools.xyz/markdown/learn/revert-gas-cost/index.md"
    },
    {
      "slug": "gas-estimate-limits",
      "title": "Why estimates can be wrong",
      "summary": "Simulation describes particular inputs and state, while real execution may occur later.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/gas-estimate-limits/",
      "json": "https://ethertools.xyz/api/v1/lessons/gas-estimate-limits.json",
      "markdown": "https://ethertools.xyz/markdown/learn/gas-estimate-limits/index.md"
    },
    {
      "slug": "warm-cold-access",
      "title": "Warm versus cold access overview",
      "summary": "Access history within a transaction can affect some resource costs.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/warm-cold-access/",
      "json": "https://ethertools.xyz/api/v1/lessons/warm-cold-access.json",
      "markdown": "https://ethertools.xyz/markdown/learn/warm-cold-access/index.md"
    },
    {
      "slug": "storage-gas",
      "title": "Storage writes and gas",
      "summary": "Persistent updates have costs that depend on the state transition.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/storage-gas/",
      "json": "https://ethertools.xyz/api/v1/lessons/storage-gas.json",
      "markdown": "https://ethertools.xyz/markdown/learn/storage-gas/index.md"
    },
    {
      "slug": "gas-refunds",
      "title": "Gas refunds and refund limits",
      "summary": "A refund counter follows specific rules and is capped.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/gas-refunds/",
      "json": "https://ethertools.xyz/api/v1/lessons/gas-refunds.json",
      "markdown": "https://ethertools.xyz/markdown/learn/gas-refunds/index.md"
    },
    {
      "slug": "execution-blob-fees",
      "title": "Execution fees versus blob fees",
      "summary": "Blob-carrying transactions have an additional data-resource dimension.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/execution-blob-fees/",
      "json": "https://ethertools.xyz/api/v1/lessons/execution-blob-fees.json",
      "markdown": "https://ethertools.xyz/markdown/learn/execution-blob-fees/index.md"
    },
    {
      "slug": "l2-fee-components",
      "title": "Layer 2 fee components",
      "summary": "Execution and data-related costs can be combined differently by each network.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/l2-fee-components/",
      "json": "https://ethertools.xyz/api/v1/lessons/l2-fee-components.json",
      "markdown": "https://ethertools.xyz/markdown/learn/l2-fee-components/index.md"
    },
    {
      "slug": "manual-fee-budget",
      "title": "Build a manual fee budget",
      "summary": "State your assumptions and keep permitted maximums apart from expected costs.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/manual-fee-budget/",
      "json": "https://ethertools.xyz/api/v1/lessons/manual-fee-budget.json",
      "markdown": "https://ethertools.xyz/markdown/learn/manual-fee-budget/index.md"
    },
    {
      "slug": "gas-practice",
      "title": "Gas calculation practice set",
      "summary": "Use both units and fee caps to explain a result.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/gas-practice/",
      "json": "https://ethertools.xyz/api/v1/lessons/gas-practice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/gas-practice/index.md"
    },
    {
      "slug": "nodes",
      "title": "Nodes and the shared state",
      "summary": "Computers that check the rules instead of trusting someone else’s copy.",
      "level": "intermediate",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/nodes/",
      "json": "https://ethertools.xyz/api/v1/lessons/nodes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/nodes/index.md"
    },
    {
      "slug": "proof-of-stake",
      "title": "How Ethereum agrees",
      "summary": "Validators propose and vote; nodes check that the rules hold.",
      "level": "intermediate",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/proof-of-stake/",
      "json": "https://ethertools.xyz/api/v1/lessons/proof-of-stake.json",
      "markdown": "https://ethertools.xyz/markdown/learn/proof-of-stake/index.md"
    },
    {
      "slug": "execution-consensus-clients",
      "title": "Execution clients and consensus clients",
      "summary": "Two cooperating roles check execution and follow proof-of-stake consensus.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/execution-consensus-clients/",
      "json": "https://ethertools.xyz/api/v1/lessons/execution-consensus-clients.json",
      "markdown": "https://ethertools.xyz/markdown/learn/execution-consensus-clients/index.md"
    },
    {
      "slug": "nodes-vs-validators",
      "title": "Nodes versus validators",
      "summary": "Verifying the chain and participating with stake are distinct roles.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/nodes-vs-validators/",
      "json": "https://ethertools.xyz/api/v1/lessons/nodes-vs-validators.json",
      "markdown": "https://ethertools.xyz/markdown/learn/nodes-vs-validators/index.md"
    },
    {
      "slug": "full-node-verification",
      "title": "What does a full node verify?",
      "summary": "It applies protocol rules rather than accepting a provider’s labels as proof.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/full-node-verification/",
      "json": "https://ethertools.xyz/api/v1/lessons/full-node-verification.json",
      "markdown": "https://ethertools.xyz/markdown/learn/full-node-verification/index.md"
    },
    {
      "slug": "archive-node",
      "title": "What an archive node retains",
      "summary": "Historical state access differs from merely retaining block history.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/archive-node/",
      "json": "https://ethertools.xyz/api/v1/lessons/archive-node.json",
      "markdown": "https://ethertools.xyz/markdown/learn/archive-node/index.md"
    },
    {
      "slug": "p2p-networking",
      "title": "Peer-to-peer networking basics",
      "summary": "Nodes exchange data through many connections rather than one universal message queue.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/p2p-networking/",
      "json": "https://ethertools.xyz/api/v1/lessons/p2p-networking.json",
      "markdown": "https://ethertools.xyz/markdown/learn/p2p-networking/index.md"
    },
    {
      "slug": "slots",
      "title": "What happens in a slot?",
      "summary": "The consensus schedule gives an opportunity for a block proposal.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/slots/",
      "json": "https://ethertools.xyz/api/v1/lessons/slots.json",
      "markdown": "https://ethertools.xyz/markdown/learn/slots/index.md"
    },
    {
      "slug": "epochs",
      "title": "What happens in an epoch?",
      "summary": "Groups of slots provide a larger structure for consensus duties and checkpoints.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/epochs/",
      "json": "https://ethertools.xyz/api/v1/lessons/epochs.json",
      "markdown": "https://ethertools.xyz/markdown/learn/epochs/index.md"
    },
    {
      "slug": "block-proposer",
      "title": "Block proposers explained",
      "summary": "The selected proposer offers a candidate block; the network checks it.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/block-proposer/",
      "json": "https://ethertools.xyz/api/v1/lessons/block-proposer.json",
      "markdown": "https://ethertools.xyz/markdown/learn/block-proposer/index.md"
    },
    {
      "slug": "attestations",
      "title": "Attestations explained",
      "summary": "Validators publish structured votes about chain and checkpoint views.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/attestations/",
      "json": "https://ethertools.xyz/api/v1/lessons/attestations.json",
      "markdown": "https://ethertools.xyz/markdown/learn/attestations/index.md"
    },
    {
      "slug": "fork-choice",
      "title": "Fork choice in plain language",
      "summary": "A node needs a rule for choosing its current valid chain head.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/fork-choice/",
      "json": "https://ethertools.xyz/api/v1/lessons/fork-choice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fork-choice/index.md"
    },
    {
      "slug": "checkpoints-finality",
      "title": "Checkpoints and finality",
      "summary": "Consensus can make a stronger commitment to accepted history.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/checkpoints-finality/",
      "json": "https://ethertools.xyz/api/v1/lessons/checkpoints-finality.json",
      "markdown": "https://ethertools.xyz/markdown/learn/checkpoints-finality/index.md"
    },
    {
      "slug": "validator-rewards-penalties",
      "title": "Validator rewards and penalties",
      "summary": "The protocol gives incentives for correct participation and costs for failures.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/validator-rewards-penalties/",
      "json": "https://ethertools.xyz/api/v1/lessons/validator-rewards-penalties.json",
      "markdown": "https://ethertools.xyz/markdown/learn/validator-rewards-penalties/index.md"
    },
    {
      "slug": "slashing",
      "title": "What slashing means",
      "summary": "Some conflicting validator actions can be proven and penalized by the protocol.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/slashing/",
      "json": "https://ethertools.xyz/api/v1/lessons/slashing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/slashing/index.md"
    },
    {
      "slug": "client-diversity",
      "title": "Why client diversity matters",
      "summary": "Independent implementations can reduce dependence on one shared software bug.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/client-diversity/",
      "json": "https://ethertools.xyz/api/v1/lessons/client-diversity.json",
      "markdown": "https://ethertools.xyz/markdown/learn/client-diversity/index.md"
    },
    {
      "slug": "light-client",
      "title": "What a light client checks",
      "summary": "A lighter verification design uses authenticated summaries and proofs under stated assumptions.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/light-client/",
      "json": "https://ethertools.xyz/api/v1/lessons/light-client.json",
      "markdown": "https://ethertools.xyz/markdown/learn/light-client/index.md"
    },
    {
      "slug": "rpc-provider-trust",
      "title": "Trusting an RPC provider",
      "summary": "A convenient access point adds assumptions about answers, privacy and availability.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/rpc-provider-trust/",
      "json": "https://ethertools.xyz/api/v1/lessons/rpc-provider-trust.json",
      "markdown": "https://ethertools.xyz/markdown/learn/rpc-provider-trust/index.md"
    },
    {
      "slug": "rpc-reads-writes",
      "title": "Read calls versus write transactions",
      "summary": "Simulation, submission and accepted state updates are separate operations.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/rpc-reads-writes/",
      "json": "https://ethertools.xyz/api/v1/lessons/rpc-reads-writes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/rpc-reads-writes/index.md"
    },
    {
      "slug": "network-architecture-check",
      "title": "Network architecture knowledge check",
      "summary": "Connect verification, consensus, providers and local tools without mixing their roles.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/network-architecture-check/",
      "json": "https://ethertools.xyz/api/v1/lessons/network-architecture-check.json",
      "markdown": "https://ethertools.xyz/markdown/learn/network-architecture-check/index.md"
    },
    {
      "slug": "layer-2",
      "title": "Layer 2 and rollups",
      "summary": "Do more work elsewhere, with verification tied back to Ethereum.",
      "level": "intermediate",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/layer-2/",
      "json": "https://ethertools.xyz/api/v1/lessons/layer-2.json",
      "markdown": "https://ethertools.xyz/markdown/learn/layer-2/index.md"
    },
    {
      "slug": "layer1-layer2",
      "title": "Layer 1 versus layer 2",
      "summary": "Execution can happen on another system while settlement relates back to Ethereum.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/layer1-layer2/",
      "json": "https://ethertools.xyz/api/v1/lessons/layer1-layer2.json",
      "markdown": "https://ethertools.xyz/markdown/learn/layer1-layer2/index.md"
    },
    {
      "slug": "rollup-batches",
      "title": "What is a rollup batch?",
      "summary": "Many local transactions can contribute to one published unit of information.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/rollup-batches/",
      "json": "https://ethertools.xyz/api/v1/lessons/rollup-batches.json",
      "markdown": "https://ethertools.xyz/markdown/learn/rollup-batches/index.md"
    },
    {
      "slug": "optimistic-rollups",
      "title": "Optimistic rollups explained",
      "summary": "State claims can be accepted provisionally under a challenge mechanism.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/optimistic-rollups/",
      "json": "https://ethertools.xyz/api/v1/lessons/optimistic-rollups.json",
      "markdown": "https://ethertools.xyz/markdown/learn/optimistic-rollups/index.md"
    },
    {
      "slug": "validity-rollups",
      "title": "Validity rollups explained",
      "summary": "A verifier checks a proof that a state transition follows the encoded rules.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/validity-rollups/",
      "json": "https://ethertools.xyz/api/v1/lessons/validity-rollups.json",
      "markdown": "https://ethertools.xyz/markdown/learn/validity-rollups/index.md"
    },
    {
      "slug": "fault-proof-windows",
      "title": "Fraud proofs and challenge periods",
      "summary": "A dispute process needs evidence, access and time to work.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/fault-proof-windows/",
      "json": "https://ethertools.xyz/api/v1/lessons/fault-proof-windows.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fault-proof-windows/index.md"
    },
    {
      "slug": "validity-proof-verification",
      "title": "Validity proofs and verification",
      "summary": "The checked statement matters as much as the proof’s name.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/validity-proof-verification/",
      "json": "https://ethertools.xyz/api/v1/lessons/validity-proof-verification.json",
      "markdown": "https://ethertools.xyz/markdown/learn/validity-proof-verification/index.md"
    },
    {
      "slug": "sequencers",
      "title": "What is a sequencer?",
      "summary": "An ordering service can give a rollup its immediate transaction sequence.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/sequencers/",
      "json": "https://ethertools.xyz/api/v1/lessons/sequencers.json",
      "markdown": "https://ethertools.xyz/markdown/learn/sequencers/index.md"
    },
    {
      "slug": "sequencer-exit-paths",
      "title": "Sequencer availability and escape paths",
      "summary": "A fallback must work under the conditions where the ordinary path fails.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/sequencer-exit-paths/",
      "json": "https://ethertools.xyz/api/v1/lessons/sequencer-exit-paths.json",
      "markdown": "https://ethertools.xyz/markdown/learn/sequencer-exit-paths/index.md"
    },
    {
      "slug": "settlement-execution",
      "title": "Settlement versus execution",
      "summary": "Running a transaction and committing to its accepted result are related but different stages.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/settlement-execution/",
      "json": "https://ethertools.xyz/api/v1/lessons/settlement-execution.json",
      "markdown": "https://ethertools.xyz/markdown/learn/settlement-execution/index.md"
    },
    {
      "slug": "data-availability",
      "title": "What is data availability?",
      "summary": "Participants need access to the data required to reconstruct or check the system.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/data-availability/",
      "json": "https://ethertools.xyz/api/v1/lessons/data-availability.json",
      "markdown": "https://ethertools.xyz/markdown/learn/data-availability/index.md"
    },
    {
      "slug": "blob-data",
      "title": "Blob data in plain language",
      "summary": "A separate data channel supports scaling use cases with specific access and retention rules.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/blob-data/",
      "json": "https://ethertools.xyz/api/v1/lessons/blob-data.json",
      "markdown": "https://ethertools.xyz/markdown/learn/blob-data/index.md"
    },
    {
      "slug": "bridge-risk",
      "title": "Bridges as separate risk systems",
      "summary": "Moving claims between networks introduces additional verification and custody mechanisms.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/bridge-risk/",
      "json": "https://ethertools.xyz/api/v1/lessons/bridge-risk.json",
      "markdown": "https://ethertools.xyz/markdown/learn/bridge-risk/index.md"
    },
    {
      "slug": "canonical-third-party-bridges",
      "title": "Canonical bridges versus third-party bridges",
      "summary": "An ecosystem’s standard path and another service can use different mechanisms.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/canonical-third-party-bridges/",
      "json": "https://ethertools.xyz/api/v1/lessons/canonical-third-party-bridges.json",
      "markdown": "https://ethertools.xyz/markdown/learn/canonical-third-party-bridges/index.md"
    },
    {
      "slug": "deposits-withdrawals",
      "title": "Deposits and withdrawals",
      "summary": "Cross-layer transfers have direction-specific steps and conditions.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/deposits-withdrawals/",
      "json": "https://ethertools.xyz/api/v1/lessons/deposits-withdrawals.json",
      "markdown": "https://ethertools.xyz/markdown/learn/deposits-withdrawals/index.md"
    },
    {
      "slug": "withdrawal-timing",
      "title": "Why withdrawal timing differs",
      "summary": "Proof systems, challenge rules and service models lead to different timelines.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/withdrawal-timing/",
      "json": "https://ethertools.xyz/api/v1/lessons/withdrawal-timing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/withdrawal-timing/index.md"
    },
    {
      "slug": "sidechains",
      "title": "What is a sidechain?",
      "summary": "A separate chain can connect to Ethereum while using a different consensus security model.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/sidechains/",
      "json": "https://ethertools.xyz/api/v1/lessons/sidechains.json",
      "markdown": "https://ethertools.xyz/markdown/learn/sidechains/index.md"
    },
    {
      "slug": "network-chain-ids",
      "title": "Network IDs and chain IDs",
      "summary": "Identifiers have protocol roles beyond a wallet’s editable display name.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/network-chain-ids/",
      "json": "https://ethertools.xyz/api/v1/lessons/network-chain-ids.json",
      "markdown": "https://ethertools.xyz/markdown/learn/network-chain-ids/index.md"
    },
    {
      "slug": "scaling-trust-assumptions",
      "title": "Compare scaling trust assumptions",
      "summary": "Evaluate evidence, data and control rather than a single speed claim.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/scaling-trust-assumptions/",
      "json": "https://ethertools.xyz/api/v1/lessons/scaling-trust-assumptions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/scaling-trust-assumptions/index.md"
    },
    {
      "slug": "layer2-practice",
      "title": "Layer 2 scenario practice",
      "summary": "Separate immediate feedback, publication, settlement and exit rights.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/layer2-practice/",
      "json": "https://ethertools.xyz/api/v1/lessons/layer2-practice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/layer2-practice/index.md"
    },
    {
      "slug": "defi",
      "title": "DeFi without the hype",
      "summary": "Financial applications built from programmable contracts.",
      "level": "intermediate",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/defi/",
      "json": "https://ethertools.xyz/api/v1/lessons/defi.json",
      "markdown": "https://ethertools.xyz/markdown/learn/defi/index.md"
    },
    {
      "slug": "ethereum-payments",
      "title": "Payments with Ethereum",
      "summary": "A transfer combines an asset amount with a network and destination.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/ethereum-payments/",
      "json": "https://ethertools.xyz/api/v1/lessons/ethereum-payments.json",
      "markdown": "https://ethertools.xyz/markdown/learn/ethereum-payments/index.md"
    },
    {
      "slug": "everyday-stablecoins",
      "title": "Stablecoins for everyday use",
      "summary": "A familiar price target does not remove network, issuer or contract assumptions.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/everyday-stablecoins/",
      "json": "https://ethertools.xyz/api/v1/lessons/everyday-stablecoins.json",
      "markdown": "https://ethertools.xyz/markdown/learn/everyday-stablecoins/index.md"
    },
    {
      "slug": "decentralized-exchanges",
      "title": "Decentralized exchanges explained",
      "summary": "Contract rules can coordinate swaps, with dependencies that still need review.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/decentralized-exchanges/",
      "json": "https://ethertools.xyz/api/v1/lessons/decentralized-exchanges.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decentralized-exchanges/index.md"
    },
    {
      "slug": "liquidity-pools",
      "title": "Liquidity pools explained",
      "summary": "A pool’s reserves and pricing rule shape what a swap can receive.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/liquidity-pools/",
      "json": "https://ethertools.xyz/api/v1/lessons/liquidity-pools.json",
      "markdown": "https://ethertools.xyz/markdown/learn/liquidity-pools/index.md"
    },
    {
      "slug": "price-impact-slippage",
      "title": "Price impact versus slippage",
      "summary": "Your trade can move a price, while execution can also differ from a prior quote.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/price-impact-slippage/",
      "json": "https://ethertools.xyz/api/v1/lessons/price-impact-slippage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/price-impact-slippage/index.md"
    },
    {
      "slug": "lending-collateral",
      "title": "Lending and collateral",
      "summary": "Borrowing systems define rules for debt, security and repayment.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/lending-collateral/",
      "json": "https://ethertools.xyz/api/v1/lessons/lending-collateral.json",
      "markdown": "https://ethertools.xyz/markdown/learn/lending-collateral/index.md"
    },
    {
      "slug": "liquidation",
      "title": "Liquidation explained",
      "summary": "A system can permit closing or reducing a position when its conditions are breached.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/liquidation/",
      "json": "https://ethertools.xyz/api/v1/lessons/liquidation.json",
      "markdown": "https://ethertools.xyz/markdown/learn/liquidation/index.md"
    },
    {
      "slug": "interest-rate-models",
      "title": "Interest rate models at a glance",
      "summary": "A rate can depend on pool state and a contract-defined formula.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/interest-rate-models/",
      "json": "https://ethertools.xyz/api/v1/lessons/interest-rate-models.json",
      "markdown": "https://ethertools.xyz/markdown/learn/interest-rate-models/index.md"
    },
    {
      "slug": "financial-oracles",
      "title": "Oracles in financial apps",
      "summary": "Price inputs can determine borrowing, liquidations and swaps.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/financial-oracles/",
      "json": "https://ethertools.xyz/api/v1/lessons/financial-oracles.json",
      "markdown": "https://ethertools.xyz/markdown/learn/financial-oracles/index.md"
    },
    {
      "slug": "dao-intro",
      "title": "DAOs and shared decisions",
      "summary": "Groups can express some governance rules through contracts and coordinated processes.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/dao-intro/",
      "json": "https://ethertools.xyz/api/v1/lessons/dao-intro.json",
      "markdown": "https://ethertools.xyz/markdown/learn/dao-intro/index.md"
    },
    {
      "slug": "governance-proposals",
      "title": "Governance proposals and voting",
      "summary": "A proposal’s bytes and execution conditions matter alongside its description.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/governance-proposals/",
      "json": "https://ethertools.xyz/api/v1/lessons/governance-proposals.json",
      "markdown": "https://ethertools.xyz/markdown/learn/governance-proposals/index.md"
    },
    {
      "slug": "voting-power-ownership",
      "title": "Voting power versus ownership",
      "summary": "Control rights are defined by mechanisms rather than a universal one-token meaning.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/voting-power-ownership/",
      "json": "https://ethertools.xyz/api/v1/lessons/voting-power-ownership.json",
      "markdown": "https://ethertools.xyz/markdown/learn/voting-power-ownership/index.md"
    },
    {
      "slug": "decentralized-identity",
      "title": "Decentralized identity explained",
      "summary": "Identifiers, claims and verification rules can be controlled and checked in different ways.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/decentralized-identity/",
      "json": "https://ethertools.xyz/api/v1/lessons/decentralized-identity.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decentralized-identity/index.md"
    },
    {
      "slug": "ens-names",
      "title": "ENS names explained",
      "summary": "A naming system can map a readable name to records under its rules.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/ens-names/",
      "json": "https://ethertools.xyz/api/v1/lessons/ens-names.json",
      "markdown": "https://ethertools.xyz/markdown/learn/ens-names/index.md"
    },
    {
      "slug": "public-goods-funding",
      "title": "Public goods funding explained",
      "summary": "Communities can support shared resources through several allocation mechanisms.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/public-goods-funding/",
      "json": "https://ethertools.xyz/api/v1/lessons/public-goods-funding.json",
      "markdown": "https://ethertools.xyz/markdown/learn/public-goods-funding/index.md"
    },
    {
      "slug": "collectibles-beyond-speculation",
      "title": "Digital collectibles beyond speculation",
      "summary": "Individually tracked items can support membership, games and other experiences.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/collectibles-beyond-speculation/",
      "json": "https://ethertools.xyz/api/v1/lessons/collectibles-beyond-speculation.json",
      "markdown": "https://ethertools.xyz/markdown/learn/collectibles-beyond-speculation/index.md"
    },
    {
      "slug": "account-abstraction-users",
      "title": "Account abstraction for users",
      "summary": "Programmable authorization can change how a wallet feels without removing execution costs.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/account-abstraction-users/",
      "json": "https://ethertools.xyz/api/v1/lessons/account-abstraction-users.json",
      "markdown": "https://ethertools.xyz/markdown/learn/account-abstraction-users/index.md"
    },
    {
      "slug": "composability-risk",
      "title": "Composability and shared risk",
      "summary": "Applications can connect useful components and inherit their dependencies.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/composability-risk/",
      "json": "https://ethertools.xyz/api/v1/lessons/composability-risk.json",
      "markdown": "https://ethertools.xyz/markdown/learn/composability-risk/index.md"
    },
    {
      "slug": "application-risk-check",
      "title": "Application risk knowledge check",
      "summary": "Identify the mechanism behind the familiar screen.",
      "level": "intermediate",
      "minutes": 3,
      "url": "https://ethertools.xyz/learn/application-risk-check/",
      "json": "https://ethertools.xyz/api/v1/lessons/application-risk-check.json",
      "markdown": "https://ethertools.xyz/markdown/learn/application-risk-check/index.md"
    },
    {
      "slug": "solidity",
      "title": "Read your first Solidity contract",
      "summary": "Variables hold values. Functions describe the changes you allow.",
      "level": "advanced",
      "minutes": 7,
      "url": "https://ethertools.xyz/learn/solidity/",
      "json": "https://ethertools.xyz/api/v1/lessons/solidity.json",
      "markdown": "https://ethertools.xyz/markdown/learn/solidity/index.md"
    },
    {
      "slug": "solidity-file",
      "title": "A Solidity source file explained",
      "summary": "Separate metadata, compiler constraints and declarations before reading function logic.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/solidity-file/",
      "json": "https://ethertools.xyz/api/v1/lessons/solidity-file.json",
      "markdown": "https://ethertools.xyz/markdown/learn/solidity-file/index.md"
    },
    {
      "slug": "pragma-versions",
      "title": "Pragma directives and compiler versions",
      "summary": "A source constraint and the compiler actually used are different pieces of evidence.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/pragma-versions/",
      "json": "https://ethertools.xyz/api/v1/lessons/pragma-versions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/pragma-versions/index.md"
    },
    {
      "slug": "constructors",
      "title": "Contract declarations and constructors",
      "summary": "Creation-time setup differs from later runtime calls.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/constructors/",
      "json": "https://ethertools.xyz/api/v1/lessons/constructors.json",
      "markdown": "https://ethertools.xyz/markdown/learn/constructors/index.md"
    },
    {
      "slug": "bool-integer-types",
      "title": "Boolean and integer types",
      "summary": "Types define representable values and operations, not economic meaning.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/bool-integer-types/",
      "json": "https://ethertools.xyz/api/v1/lessons/bool-integer-types.json",
      "markdown": "https://ethertools.xyz/markdown/learn/bool-integer-types/index.md"
    },
    {
      "slug": "signed-unsigned",
      "title": "Signed versus unsigned integers",
      "summary": "Negative values require a representation and range appropriate to the task.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/signed-unsigned/",
      "json": "https://ethertools.xyz/api/v1/lessons/signed-unsigned.json",
      "markdown": "https://ethertools.xyz/markdown/learn/signed-unsigned/index.md"
    },
    {
      "slug": "address-payable",
      "title": "Addresses and payable addresses",
      "summary": "An address representation and permission to use value-transfer syntax are different concepts.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/address-payable/",
      "json": "https://ethertools.xyz/api/v1/lessons/address-payable.json",
      "markdown": "https://ethertools.xyz/markdown/learn/address-payable/index.md"
    },
    {
      "slug": "fixed-dynamic-bytes",
      "title": "Fixed bytes versus dynamic bytes",
      "summary": "A fixed-size byte value differs from a variable-length byte sequence.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/fixed-dynamic-bytes/",
      "json": "https://ethertools.xyz/api/v1/lessons/fixed-dynamic-bytes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fixed-dynamic-bytes/index.md"
    },
    {
      "slug": "strings-utf8",
      "title": "Strings and UTF-8",
      "summary": "Byte length and visible character count can differ.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/strings-utf8/",
      "json": "https://ethertools.xyz/api/v1/lessons/strings-utf8.json",
      "markdown": "https://ethertools.xyz/markdown/learn/strings-utf8/index.md"
    },
    {
      "slug": "state-local-variables",
      "title": "State variables versus local variables",
      "summary": "Persistence depends on where a value lives and how it is updated.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/state-local-variables/",
      "json": "https://ethertools.xyz/api/v1/lessons/state-local-variables.json",
      "markdown": "https://ethertools.xyz/markdown/learn/state-local-variables/index.md"
    },
    {
      "slug": "visibility",
      "title": "Functions and visibility",
      "summary": "Call reachability and business authorization are separate layers.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/visibility/",
      "json": "https://ethertools.xyz/api/v1/lessons/visibility.json",
      "markdown": "https://ethertools.xyz/markdown/learn/visibility/index.md"
    },
    {
      "slug": "view-pure",
      "title": "View and pure functions",
      "summary": "State-access restrictions differ from whether execution happens inside a paid transaction.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/view-pure/",
      "json": "https://ethertools.xyz/api/v1/lessons/view-pure.json",
      "markdown": "https://ethertools.xyz/markdown/learn/view-pure/index.md"
    },
    {
      "slug": "parameters-returns",
      "title": "Function parameters and return values",
      "summary": "Inputs and outputs have typed ABI shapes with different call-data framing.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/parameters-returns/",
      "json": "https://ethertools.xyz/api/v1/lessons/parameters-returns.json",
      "markdown": "https://ethertools.xyz/markdown/learn/parameters-returns/index.md"
    },
    {
      "slug": "require-revert-assert",
      "title": "Require, revert and assert",
      "summary": "Failure mechanisms express different conditions and error shapes.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/require-revert-assert/",
      "json": "https://ethertools.xyz/api/v1/lessons/require-revert-assert.json",
      "markdown": "https://ethertools.xyz/markdown/learn/require-revert-assert/index.md"
    },
    {
      "slug": "modifiers",
      "title": "Modifiers and access checks",
      "summary": "Reusable wrappers can enforce conditions, but the full code path matters.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/modifiers/",
      "json": "https://ethertools.xyz/api/v1/lessons/modifiers.json",
      "markdown": "https://ethertools.xyz/markdown/learn/modifiers/index.md"
    },
    {
      "slug": "solidity-events",
      "title": "Events in a contract",
      "summary": "Logs help applications observe defined execution records.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/solidity-events/",
      "json": "https://ethertools.xyz/api/v1/lessons/solidity-events.json",
      "markdown": "https://ethertools.xyz/markdown/learn/solidity-events/index.md"
    },
    {
      "slug": "custom-errors-solidity",
      "title": "Custom errors in Solidity",
      "summary": "Typed failures can encode useful context compactly.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/custom-errors-solidity/",
      "json": "https://ethertools.xyz/api/v1/lessons/custom-errors-solidity.json",
      "markdown": "https://ethertools.xyz/markdown/learn/custom-errors-solidity/index.md"
    },
    {
      "slug": "interfaces-inheritance",
      "title": "Interfaces and inheritance basics",
      "summary": "Shared declarations and inherited implementation have different jobs.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/interfaces-inheritance/",
      "json": "https://ethertools.xyz/api/v1/lessons/interfaces-inheritance.json",
      "markdown": "https://ethertools.xyz/markdown/learn/interfaces-inheritance/index.md"
    },
    {
      "slug": "receive-fallback",
      "title": "Receive and fallback functions",
      "summary": "Special entry points handle certain calls outside ordinary named-function dispatch.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/receive-fallback/",
      "json": "https://ethertools.xyz/api/v1/lessons/receive-fallback.json",
      "markdown": "https://ethertools.xyz/markdown/learn/receive-fallback/index.md"
    },
    {
      "slug": "read-small-contract",
      "title": "Read a complete small contract",
      "summary": "Trace inputs, permission, state and logs in one self-contained example.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/read-small-contract/",
      "json": "https://ethertools.xyz/api/v1/lessons/read-small-contract.json",
      "markdown": "https://ethertools.xyz/markdown/learn/read-small-contract/index.md"
    },
    {
      "slug": "abi",
      "title": "ABI: the contract’s interface",
      "summary": "Turn a function name and typed arguments into bytes.",
      "level": "advanced",
      "minutes": 8,
      "url": "https://ethertools.xyz/learn/abi/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi/index.md"
    },
    {
      "slug": "calldata",
      "title": "Trace calldata byte by byte",
      "summary": "Find the selector, split the words, and follow dynamic offsets.",
      "level": "advanced",
      "minutes": 9,
      "url": "https://ethertools.xyz/learn/calldata/",
      "json": "https://ethertools.xyz/api/v1/lessons/calldata.json",
      "markdown": "https://ethertools.xyz/markdown/learn/calldata/index.md"
    },
    {
      "slug": "canonical-signatures",
      "title": "Canonical function signatures",
      "summary": "Normalize the name and parameter types before hashing a selector.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/canonical-signatures/",
      "json": "https://ethertools.xyz/api/v1/lessons/canonical-signatures.json",
      "markdown": "https://ethertools.xyz/markdown/learn/canonical-signatures/index.md"
    },
    {
      "slug": "function-selectors",
      "title": "Calculate a function selector",
      "summary": "Keep the first four bytes of the canonical signature’s Keccak-256 digest.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/function-selectors/",
      "json": "https://ethertools.xyz/api/v1/lessons/function-selectors.json",
      "markdown": "https://ethertools.xyz/markdown/learn/function-selectors/index.md"
    },
    {
      "slug": "abi-uint256",
      "title": "Encode uint256 step by step",
      "summary": "An unsigned integer occupies one left-padded 32-byte word.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-uint256/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-uint256.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-uint256/index.md"
    },
    {
      "slug": "abi-signed-integers",
      "title": "Encode signed integers",
      "summary": "Negative values use two’s-complement and sign extension.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-signed-integers/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-signed-integers.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-signed-integers/index.md"
    },
    {
      "slug": "abi-address-word",
      "title": "Encode an address word",
      "summary": "Twenty address bytes occupy the lower-order part of a word.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-address-word/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-address-word.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-address-word/index.md"
    },
    {
      "slug": "abi-boolean-word",
      "title": "Encode a boolean word",
      "summary": "The boolean schema uses canonical zero or one values.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-boolean-word/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-boolean-word.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-boolean-word/index.md"
    },
    {
      "slug": "abi-fixed-bytes",
      "title": "Encode bytes4 versus bytes32",
      "summary": "Fixed bytes are right-padded, unlike unsigned integers.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-fixed-bytes/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-fixed-bytes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-fixed-bytes/index.md"
    },
    {
      "slug": "abi-static-tuples",
      "title": "Static tuples explained",
      "summary": "A tuple of static members concatenates their encodings without an offset to a tail.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-static-tuples/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-static-tuples.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-static-tuples/index.md"
    },
    {
      "slug": "abi-fixed-arrays",
      "title": "Fixed-size arrays in the ABI",
      "summary": "A fixed count does not automatically make the entire value static.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-fixed-arrays/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-fixed-arrays.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-fixed-arrays/index.md"
    },
    {
      "slug": "abi-return-data",
      "title": "ABI return values without selectors",
      "summary": "Ordinary result data begins with the output tuple encoding.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-return-data/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-return-data.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-return-data/index.md"
    },
    {
      "slug": "abi-multiple-returns",
      "title": "Decode multiple return values",
      "summary": "Read the output tuple in its declared order.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-multiple-returns/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-multiple-returns.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-multiple-returns/index.md"
    },
    {
      "slug": "abi-overloads",
      "title": "Function overloads and selectors",
      "summary": "The same name can identify different input-type signatures.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-overloads/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-overloads.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-overloads/index.md"
    },
    {
      "slug": "json-abi",
      "title": "The JSON ABI format",
      "summary": "Structured interface entries describe functions, events and errors.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/json-abi/",
      "json": "https://ethertools.xyz/api/v1/lessons/json-abi.json",
      "markdown": "https://ethertools.xyz/markdown/learn/json-abi/index.md"
    },
    {
      "slug": "abi-not-self-describing",
      "title": "Why ABI data is not self-describing",
      "summary": "A valid word can support several different interpretations.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-not-self-describing/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-not-self-describing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-not-self-describing/index.md"
    },
    {
      "slug": "selector-collisions",
      "title": "Selector collisions explained",
      "summary": "Four bytes cannot uniquely label every possible function signature.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/selector-collisions/",
      "json": "https://ethertools.xyz/api/v1/lessons/selector-collisions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/selector-collisions/index.md"
    },
    {
      "slug": "abi-vs-packed",
      "title": "ABI encoding versus packed encoding",
      "summary": "Compact concatenation has different boundaries and ambiguity properties.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-vs-packed/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-vs-packed.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-vs-packed/index.md"
    },
    {
      "slug": "erc20-calldata-walkthrough",
      "title": "A complete ERC-20 calldata walkthrough",
      "summary": "Separate action selector, recipient and raw token amount.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/erc20-calldata-walkthrough/",
      "json": "https://ethertools.xyz/api/v1/lessons/erc20-calldata-walkthrough.json",
      "markdown": "https://ethertools.xyz/markdown/learn/erc20-calldata-walkthrough/index.md"
    },
    {
      "slug": "static-abi-practice",
      "title": "Static ABI decoding challenge set",
      "summary": "Use the schema, padding and complete static width together.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/static-abi-practice/",
      "json": "https://ethertools.xyz/api/v1/lessons/static-abi-practice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/static-abi-practice/index.md"
    },
    {
      "slug": "abi-head-tail",
      "title": "Head and tail encoding",
      "summary": "Keep fixed-width heads separate from variable-sized payloads.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-head-tail/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-head-tail.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-head-tail/index.md"
    },
    {
      "slug": "abi-relative-offsets",
      "title": "Understand relative offsets",
      "summary": "An offset is useful only when you know its starting point.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-relative-offsets/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-relative-offsets.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-relative-offsets/index.md"
    },
    {
      "slug": "abi-one-string",
      "title": "Encode one string",
      "summary": "A single dynamic argument still has an offset word.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-one-string/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-one-string.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-one-string/index.md"
    },
    {
      "slug": "abi-utf8-length",
      "title": "Count UTF-8 bytes correctly",
      "summary": "Visible characters and encoded bytes are different counts.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-utf8-length/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-utf8-length.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-utf8-length/index.md"
    },
    {
      "slug": "abi-dynamic-padding",
      "title": "Padding dynamic bytes",
      "summary": "The payload is right-padded while its length remains exact.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-dynamic-padding/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-dynamic-padding.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-dynamic-padding/index.md"
    },
    {
      "slug": "abi-two-dynamic",
      "title": "Encode two dynamic arguments",
      "summary": "Later tails begin after the full earlier tail.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-two-dynamic/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-two-dynamic.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-two-dynamic/index.md"
    },
    {
      "slug": "abi-uint-array",
      "title": "Encode a uint256 array",
      "summary": "Dynamic arrays begin their tail with an element count.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-uint-array/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-uint-array.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-uint-array/index.md"
    },
    {
      "slug": "abi-string-array",
      "title": "Encode a string array",
      "summary": "Element offsets use the array element tuple as their base.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-string-array/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-string-array.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-string-array/index.md"
    },
    {
      "slug": "abi-fixed-dynamic-array",
      "title": "Fixed arrays of dynamic values",
      "summary": "A fixed element count can still contain dynamic content.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-fixed-dynamic-array/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-fixed-dynamic-array.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-fixed-dynamic-array/index.md"
    },
    {
      "slug": "abi-static-tuple-array",
      "title": "Dynamic arrays of static tuples",
      "summary": "The array is dynamic even when every tuple element has fixed width.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-static-tuple-array/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-static-tuple-array.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-static-tuple-array/index.md"
    },
    {
      "slug": "abi-tuple-string",
      "title": "Tuples containing strings",
      "summary": "One dynamic component makes the tuple dynamic.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-tuple-string/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-tuple-string.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-tuple-string/index.md"
    },
    {
      "slug": "abi-nested-offset-bases",
      "title": "Nested tuple offset bases",
      "summary": "Draw a separate origin for every nested dynamic tuple.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-nested-offset-bases/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-nested-offset-bases.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-nested-offset-bases/index.md"
    },
    {
      "slug": "abi-nested-dynamic-array",
      "title": "Nested dynamic array walkthrough",
      "summary": "Each dynamic array layer has a count and its own element region.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-nested-dynamic-array/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-nested-dynamic-array.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-nested-dynamic-array/index.md"
    },
    {
      "slug": "abi-empty-dynamic",
      "title": "Empty strings and empty arrays",
      "summary": "Empty content still has a valid dynamic encoding.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-empty-dynamic/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-empty-dynamic.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-empty-dynamic/index.md"
    },
    {
      "slug": "abi-malformed-offsets",
      "title": "Malformed offsets and decoding failures",
      "summary": "A word that looks like an offset can point outside the supplied data.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-malformed-offsets/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-malformed-offsets.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-malformed-offsets/index.md"
    },
    {
      "slug": "abi-decoder-bounds",
      "title": "Bounds checks in ABI decoders",
      "summary": "Every length calculation must stay inside the available input.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-decoder-bounds/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-decoder-bounds.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-decoder-bounds/index.md"
    },
    {
      "slug": "abi-coder-versions",
      "title": "ABI coder version behavior",
      "summary": "Compiler generation and decoder checks are separate from the basic layout.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-coder-versions/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-coder-versions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-coder-versions/index.md"
    },
    {
      "slug": "abi-language-consistency",
      "title": "Cross-language encoding consistency",
      "summary": "Typed values should produce the same standard bytes in different implementations.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-language-consistency/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-language-consistency.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-language-consistency/index.md"
    },
    {
      "slug": "abi-build-dynamic-trace",
      "title": "Build a dynamic encoding trace",
      "summary": "Annotate byte positions before trying to memorize a long hex string.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-build-dynamic-trace/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-build-dynamic-trace.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-build-dynamic-trace/index.md"
    },
    {
      "slug": "abi-nested-challenges",
      "title": "Nested ABI challenge set",
      "summary": "Resolve a nested layout and justify every offset base.",
      "level": "advanced",
      "minutes": 5,
      "url": "https://ethertools.xyz/learn/abi-nested-challenges/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-nested-challenges.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-nested-challenges/index.md"
    },
    {
      "slug": "events",
      "title": "Events, topics and logs",
      "summary": "Read the structured notes that contracts leave during execution.",
      "level": "advanced",
      "minutes": 7,
      "url": "https://ethertools.xyz/learn/events/",
      "json": "https://ethertools.xyz/api/v1/lessons/events.json",
      "markdown": "https://ethertools.xyz/markdown/learn/events/index.md"
    },
    {
      "slug": "reverts",
      "title": "Understand why a call reverted",
      "summary": "Separate error bytes from the underlying reason execution failed.",
      "level": "advanced",
      "minutes": 7,
      "url": "https://ethertools.xyz/learn/reverts/",
      "json": "https://ethertools.xyz/api/v1/lessons/reverts.json",
      "markdown": "https://ethertools.xyz/markdown/learn/reverts/index.md"
    },
    {
      "slug": "event-signature-hash",
      "title": "Compute an event signature hash",
      "summary": "Topic zero usually identifies the event’s canonical shape.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/event-signature-hash/",
      "json": "https://ethertools.xyz/api/v1/lessons/event-signature-hash.json",
      "markdown": "https://ethertools.xyz/markdown/learn/event-signature-hash/index.md"
    },
    {
      "slug": "indexed-event-arguments",
      "title": "Indexed versus non-indexed arguments",
      "summary": "The declaration decides which values become topics.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/indexed-event-arguments/",
      "json": "https://ethertools.xyz/api/v1/lessons/indexed-event-arguments.json",
      "markdown": "https://ethertools.xyz/markdown/learn/indexed-event-arguments/index.md"
    },
    {
      "slug": "decode-transfer-log",
      "title": "Decode an ERC-20 Transfer event",
      "summary": "Read two indexed addresses and one raw amount.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/decode-transfer-log/",
      "json": "https://ethertools.xyz/api/v1/lessons/decode-transfer-log.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decode-transfer-log/index.md"
    },
    {
      "slug": "decode-approval-log",
      "title": "Decode an Approval event",
      "summary": "An allowance record describes spending permission.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/decode-approval-log/",
      "json": "https://ethertools.xyz/api/v1/lessons/decode-approval-log.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decode-approval-log/index.md"
    },
    {
      "slug": "anonymous-events",
      "title": "Anonymous events explained",
      "summary": "An anonymous event omits the signature topic.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/anonymous-events/",
      "json": "https://ethertools.xyz/api/v1/lessons/anonymous-events.json",
      "markdown": "https://ethertools.xyz/markdown/learn/anonymous-events/index.md"
    },
    {
      "slug": "indexed-string-topics",
      "title": "Indexed strings and hashed topics",
      "summary": "An indexed string topic is a digest, not recoverable text.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/indexed-string-topics/",
      "json": "https://ethertools.xyz/api/v1/lessons/indexed-string-topics.json",
      "markdown": "https://ethertools.xyz/markdown/learn/indexed-string-topics/index.md"
    },
    {
      "slug": "receipt-log-context",
      "title": "Logs inside a receipt",
      "summary": "A receipt places surviving log records in transaction context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/receipt-log-context/",
      "json": "https://ethertools.xyz/api/v1/lessons/receipt-log-context.json",
      "markdown": "https://ethertools.xyz/markdown/learn/receipt-log-context/index.md"
    },
    {
      "slug": "reverted-logs",
      "title": "Why reverted logs do not persist",
      "summary": "Rollback removes logs from the reverted execution scope.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/reverted-logs/",
      "json": "https://ethertools.xyz/api/v1/lessons/reverted-logs.json",
      "markdown": "https://ethertools.xyz/markdown/learn/reverted-logs/index.md"
    },
    {
      "slug": "nested-event-order",
      "title": "Event ordering in nested calls",
      "summary": "Nested execution can interleave logs from different emitters.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/nested-event-order/",
      "json": "https://ethertools.xyz/api/v1/lessons/nested-event-order.json",
      "markdown": "https://ethertools.xyz/markdown/learn/nested-event-order/index.md"
    },
    {
      "slug": "decode-error-string",
      "title": "Decode Error(string)",
      "summary": "A common revert format carries a dynamic message.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/decode-error-string/",
      "json": "https://ethertools.xyz/api/v1/lessons/decode-error-string.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decode-error-string/index.md"
    },
    {
      "slug": "decode-panic",
      "title": "Decode Panic(uint256)",
      "summary": "A panic carries a numeric code instead of a free-form string.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/decode-panic/",
      "json": "https://ethertools.xyz/api/v1/lessons/decode-panic.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decode-panic/index.md"
    },
    {
      "slug": "arithmetic-panic-codes",
      "title": "Read arithmetic panic codes",
      "summary": "Different runtime failures can use different numeric categories.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/arithmetic-panic-codes/",
      "json": "https://ethertools.xyz/api/v1/lessons/arithmetic-panic-codes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/arithmetic-panic-codes/index.md"
    },
    {
      "slug": "decode-custom-error",
      "title": "Decode a custom Solidity error",
      "summary": "The error declaration supplies names and types for its payload.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/decode-custom-error/",
      "json": "https://ethertools.xyz/api/v1/lessons/decode-custom-error.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decode-custom-error/index.md"
    },
    {
      "slug": "empty-revert-data",
      "title": "Empty revert data explained",
      "summary": "A failed call can return no diagnostic bytes at all.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/empty-revert-data/",
      "json": "https://ethertools.xyz/api/v1/lessons/empty-revert-data.json",
      "markdown": "https://ethertools.xyz/markdown/learn/empty-revert-data/index.md"
    },
    {
      "slug": "bubbled-errors",
      "title": "Errors can be bubbled up",
      "summary": "A caller can pass a child’s failure bytes onward.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/bubbled-errors/",
      "json": "https://ethertools.xyz/api/v1/lessons/bubbled-errors.json",
      "markdown": "https://ethertools.xyz/markdown/learn/bubbled-errors/index.md"
    },
    {
      "slug": "spoofed-revert-bytes",
      "title": "Why revert bytes can be spoofed",
      "summary": "Recognizing an error format does not authenticate its author.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/spoofed-revert-bytes/",
      "json": "https://ethertools.xyz/api/v1/lessons/spoofed-revert-bytes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/spoofed-revert-bytes/index.md"
    },
    {
      "slug": "error-call-frame",
      "title": "Link an error to a call frame",
      "summary": "Find the first failing frame and the callers that handled it.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/error-call-frame/",
      "json": "https://ethertools.xyz/api/v1/lessons/error-call-frame.json",
      "markdown": "https://ethertools.xyz/markdown/learn/error-call-frame/index.md"
    },
    {
      "slug": "receipt-error-challenges",
      "title": "Receipt and error challenge set",
      "summary": "Combine event decoding, rollback and failure context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/receipt-error-challenges/",
      "json": "https://ethertools.xyz/api/v1/lessons/receipt-error-challenges.json",
      "markdown": "https://ethertools.xyz/markdown/learn/receipt-error-challenges/index.md"
    },
    {
      "slug": "storage",
      "title": "Solidity storage slots",
      "summary": "See how persistent values fit into 32-byte slots.",
      "level": "advanced",
      "minutes": 8,
      "url": "https://ethertools.xyz/learn/storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/storage/index.md"
    },
    {
      "slug": "storage-word",
      "title": "The 32-byte storage word",
      "summary": "Storage reads and writes address full words.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/storage-word/",
      "json": "https://ethertools.xyz/api/v1/lessons/storage-word.json",
      "markdown": "https://ethertools.xyz/markdown/learn/storage-word/index.md"
    },
    {
      "slug": "storage-packing",
      "title": "Pack adjacent value types",
      "summary": "Compatible small fields can share one slot.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/storage-packing/",
      "json": "https://ethertools.xyz/api/v1/lessons/storage-packing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/storage-packing/index.md"
    },
    {
      "slug": "storage-byte-offsets",
      "title": "Byte offsets and low-order alignment",
      "summary": "Offset zero refers to the low-order end of a packed word.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/storage-byte-offsets/",
      "json": "https://ethertools.xyz/api/v1/lessons/storage-byte-offsets.json",
      "markdown": "https://ethertools.xyz/markdown/learn/storage-byte-offsets/index.md"
    },
    {
      "slug": "struct-storage",
      "title": "Struct storage layout",
      "summary": "A struct starts a fresh slot and packs its own members.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/struct-storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/struct-storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/struct-storage/index.md"
    },
    {
      "slug": "fixed-array-storage",
      "title": "Fixed array storage layout",
      "summary": "Small array elements can pack within their reserved region.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/fixed-array-storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/fixed-array-storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fixed-array-storage/index.md"
    },
    {
      "slug": "dynamic-array-storage",
      "title": "Dynamic array base slots",
      "summary": "The declared slot holds length while a hash-derived region holds elements.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/dynamic-array-storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/dynamic-array-storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/dynamic-array-storage/index.md"
    },
    {
      "slug": "mapping-slots",
      "title": "Mapping entry slot calculations",
      "summary": "Hash the properly encoded key with the declared mapping slot.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/mapping-slots/",
      "json": "https://ethertools.xyz/api/v1/lessons/mapping-slots.json",
      "markdown": "https://ethertools.xyz/markdown/learn/mapping-slots/index.md"
    },
    {
      "slug": "nested-mapping-storage",
      "title": "Nested mappings explained",
      "summary": "Apply the mapping derivation once for each key layer.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/nested-mapping-storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/nested-mapping-storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/nested-mapping-storage/index.md"
    },
    {
      "slug": "mapping-struct-storage",
      "title": "Mapping to a struct",
      "summary": "A mapping hash selects the struct’s base slot.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/mapping-struct-storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/mapping-struct-storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/mapping-struct-storage/index.md"
    },
    {
      "slug": "short-storage-bytes",
      "title": "Short bytes and short strings in storage",
      "summary": "Up to thirty-one bytes can share a slot with their length marker.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/short-storage-bytes/",
      "json": "https://ethertools.xyz/api/v1/lessons/short-storage-bytes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/short-storage-bytes/index.md"
    },
    {
      "slug": "long-storage-bytes",
      "title": "Long bytes and strings in storage",
      "summary": "Long content moves to a hash-derived data region.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/long-storage-bytes/",
      "json": "https://ethertools.xyz/api/v1/lessons/long-storage-bytes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/long-storage-bytes/index.md"
    },
    {
      "slug": "inheritance-storage-order",
      "title": "Inheritance and storage ordering",
      "summary": "Inherited declarations participate in the final instance layout.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/inheritance-storage-order/",
      "json": "https://ethertools.xyz/api/v1/lessons/inheritance-storage-order.json",
      "markdown": "https://ethertools.xyz/markdown/learn/inheritance-storage-order/index.md"
    },
    {
      "slug": "proxy-storage-layout",
      "title": "Storage layout and proxies",
      "summary": "Delegate execution makes layout compatibility part of correctness.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/proxy-storage-layout/",
      "json": "https://ethertools.xyz/api/v1/lessons/proxy-storage-layout.json",
      "markdown": "https://ethertools.xyz/markdown/learn/proxy-storage-layout/index.md"
    },
    {
      "slug": "namespaced-storage",
      "title": "Namespaced storage explained",
      "summary": "Modules can derive separate roots for structured state.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/namespaced-storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/namespaced-storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/namespaced-storage/index.md"
    },
    {
      "slug": "memory-expansion",
      "title": "Memory expansion basics",
      "summary": "Accessing farther memory can increase execution cost.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/memory-expansion/",
      "json": "https://ethertools.xyz/api/v1/lessons/memory-expansion.json",
      "markdown": "https://ethertools.xyz/markdown/learn/memory-expansion/index.md"
    },
    {
      "slug": "free-memory-pointer",
      "title": "The free memory pointer",
      "summary": "Solidity stores its allocation pointer at memory address 0x40.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/free-memory-pointer/",
      "json": "https://ethertools.xyz/api/v1/lessons/free-memory-pointer.json",
      "markdown": "https://ethertools.xyz/markdown/learn/free-memory-pointer/index.md"
    },
    {
      "slug": "calldata-memory-copies",
      "title": "Calldata versus memory copies",
      "summary": "Read-only call input and writable working memory have different roles.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/calldata-memory-copies/",
      "json": "https://ethertools.xyz/api/v1/lessons/calldata-memory-copies.json",
      "markdown": "https://ethertools.xyz/markdown/learn/calldata-memory-copies/index.md"
    },
    {
      "slug": "transient-storage",
      "title": "Transient storage explained",
      "summary": "Transaction-scoped state differs from both persistent storage and per-frame memory.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/transient-storage/",
      "json": "https://ethertools.xyz/api/v1/lessons/transient-storage.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transient-storage/index.md"
    },
    {
      "slug": "storage-challenges",
      "title": "Storage layout challenge set",
      "summary": "Combine packing, derived slots and data-location boundaries.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/storage-challenges/",
      "json": "https://ethertools.xyz/api/v1/lessons/storage-challenges.json",
      "markdown": "https://ethertools.xyz/markdown/learn/storage-challenges/index.md"
    },
    {
      "slug": "evm",
      "title": "Step inside the EVM",
      "summary": "A stack machine that turns bytecode into checked state changes.",
      "level": "advanced",
      "minutes": 8,
      "url": "https://ethertools.xyz/learn/evm/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm/index.md"
    },
    {
      "slug": "bytecode-source",
      "title": "Bytecode versus source code",
      "summary": "The EVM executes bytes produced by a compiler, not Solidity text.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/bytecode-source/",
      "json": "https://ethertools.xyz/api/v1/lessons/bytecode-source.json",
      "markdown": "https://ethertools.xyz/markdown/learn/bytecode-source/index.md"
    },
    {
      "slug": "program-counter",
      "title": "The program counter",
      "summary": "Instruction positions are byte offsets into the executing code.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/program-counter/",
      "json": "https://ethertools.xyz/api/v1/lessons/program-counter.json",
      "markdown": "https://ethertools.xyz/markdown/learn/program-counter/index.md"
    },
    {
      "slug": "evm-stack",
      "title": "The 256-bit stack",
      "summary": "EVM stack items are full-width words with limited depth.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-stack/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-stack.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-stack/index.md"
    },
    {
      "slug": "push-dup-swap",
      "title": "PUSH, DUP and SWAP",
      "summary": "Introduce, copy and rearrange stack values.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/push-dup-swap/",
      "json": "https://ethertools.xyz/api/v1/lessons/push-dup-swap.json",
      "markdown": "https://ethertools.xyz/markdown/learn/push-dup-swap/index.md"
    },
    {
      "slug": "evm-modular-arithmetic",
      "title": "ADD, MUL and modular arithmetic",
      "summary": "Raw word arithmetic wraps modulo two to the power of 256.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-modular-arithmetic/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-modular-arithmetic.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-modular-arithmetic/index.md"
    },
    {
      "slug": "evm-signed-arithmetic",
      "title": "Signed arithmetic opcodes",
      "summary": "The same word bits can be interpreted as signed or unsigned.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-signed-arithmetic/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-signed-arithmetic.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-signed-arithmetic/index.md"
    },
    {
      "slug": "evm-bitwise",
      "title": "Bitwise AND, OR and XOR",
      "summary": "These operations combine corresponding bits across words.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-bitwise/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-bitwise.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-bitwise/index.md"
    },
    {
      "slug": "evm-shifts-bytes",
      "title": "Shifts and byte extraction",
      "summary": "Shift direction and byte numbering must be stated explicitly.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-shifts-bytes/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-shifts-bytes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-shifts-bytes/index.md"
    },
    {
      "slug": "evm-memory-ops",
      "title": "MLOAD and MSTORE",
      "summary": "Word operations use byte-addressed temporary memory.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-memory-ops/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-memory-ops.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-memory-ops/index.md"
    },
    {
      "slug": "evm-storage-ops",
      "title": "SLOAD and SSTORE",
      "summary": "Storage access uses slot keys in the current storage context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-storage-ops/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-storage-ops.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-storage-ops/index.md"
    },
    {
      "slug": "evm-calldata-ops",
      "title": "Calldata load and copy",
      "summary": "Read message input as bytes before interpreting an ABI.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-calldata-ops/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-calldata-ops.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-calldata-ops/index.md"
    },
    {
      "slug": "evm-return-data",
      "title": "Return data and copying",
      "summary": "A child call leaves a result buffer separate from its success flag.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-return-data/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-return-data.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-return-data/index.md"
    },
    {
      "slug": "evm-jumps",
      "title": "JUMP, JUMPI and JUMPDEST",
      "summary": "Control flow must target a valid destination instruction.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-jumps/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-jumps.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-jumps/index.md"
    },
    {
      "slug": "evm-halting",
      "title": "STOP, RETURN and REVERT",
      "summary": "Halting instructions differ in output and state outcome.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-halting/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-halting.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-halting/index.md"
    },
    {
      "slug": "evm-call",
      "title": "CALL opcode basics",
      "summary": "An external call creates a nested execution frame.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-call/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-call.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-call/index.md"
    },
    {
      "slug": "evm-staticcall",
      "title": "STATICCALL explained",
      "summary": "Read-only execution context prohibits state-changing operations.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-staticcall/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-staticcall.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-staticcall/index.md"
    },
    {
      "slug": "evm-delegatecall",
      "title": "DELEGATECALL and execution context",
      "summary": "Use another address’s code while retaining the caller’s state context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-delegatecall/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-delegatecall.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-delegatecall/index.md"
    },
    {
      "slug": "evm-log-opcodes",
      "title": "LOG opcodes and topics",
      "summary": "Logs are explicit EVM effects with memory data and up to four topics.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-log-opcodes/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-log-opcodes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-log-opcodes/index.md"
    },
    {
      "slug": "evm-trace-challenge",
      "title": "Trace a small EVM program",
      "summary": "Track byte positions and stack changes before reasoning about state.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-trace-challenge/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-trace-challenge.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-trace-challenge/index.md"
    },
    {
      "slug": "transaction-call-context",
      "title": "Transaction context versus call context",
      "summary": "One transaction can contain several message-call contexts.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/transaction-call-context/",
      "json": "https://ethertools.xyz/api/v1/lessons/transaction-call-context.json",
      "markdown": "https://ethertools.xyz/markdown/learn/transaction-call-context/index.md"
    },
    {
      "slug": "sender-origin",
      "title": "msg.sender versus tx.origin",
      "summary": "The immediate caller and transaction originator can differ.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/sender-origin/",
      "json": "https://ethertools.xyz/api/v1/lessons/sender-origin.json",
      "markdown": "https://ethertools.xyz/markdown/learn/sender-origin/index.md"
    },
    {
      "slug": "nested-msg-value",
      "title": "msg.value in nested calls",
      "summary": "Value belongs to a particular call context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/nested-msg-value/",
      "json": "https://ethertools.xyz/api/v1/lessons/nested-msg-value.json",
      "markdown": "https://ethertools.xyz/markdown/learn/nested-msg-value/index.md"
    },
    {
      "slug": "create-contract",
      "title": "Contract creation with CREATE",
      "summary": "Creation executes initialization code and may return runtime code.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/create-contract/",
      "json": "https://ethertools.xyz/api/v1/lessons/create-contract.json",
      "markdown": "https://ethertools.xyz/markdown/learn/create-contract/index.md"
    },
    {
      "slug": "create2-addresses",
      "title": "Deterministic creation with CREATE2",
      "summary": "Creator, salt and init-code hash determine a candidate address.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/create2-addresses/",
      "json": "https://ethertools.xyz/api/v1/lessons/create2-addresses.json",
      "markdown": "https://ethertools.xyz/markdown/learn/create2-addresses/index.md"
    },
    {
      "slug": "init-runtime-code",
      "title": "Init code versus runtime code",
      "summary": "Deployment instructions and installed instructions have different jobs.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/init-runtime-code/",
      "json": "https://ethertools.xyz/api/v1/lessons/init-runtime-code.json",
      "markdown": "https://ethertools.xyz/markdown/learn/init-runtime-code/index.md"
    },
    {
      "slug": "value-call-failures",
      "title": "Value transfer and call failures",
      "summary": "A value-bearing call can fail and must be handled deliberately.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/value-call-failures/",
      "json": "https://ethertools.xyz/api/v1/lessons/value-call-failures.json",
      "markdown": "https://ethertools.xyz/markdown/learn/value-call-failures/index.md"
    },
    {
      "slug": "call-depth-limits",
      "title": "Call depth and stack limits",
      "summary": "Frame nesting and stack item depth are separate constraints.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/call-depth-limits/",
      "json": "https://ethertools.xyz/api/v1/lessons/call-depth-limits.json",
      "markdown": "https://ethertools.xyz/markdown/learn/call-depth-limits/index.md"
    },
    {
      "slug": "gas-forwarding",
      "title": "Gas forwarding and the 63/64 rule",
      "summary": "A requested gas amount is subject to forwarding rules.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/gas-forwarding/",
      "json": "https://ethertools.xyz/api/v1/lessons/gas-forwarding.json",
      "markdown": "https://ethertools.xyz/markdown/learn/gas-forwarding/index.md"
    },
    {
      "slug": "return-data-griefing",
      "title": "Return-data griefing explained",
      "summary": "Large attacker-controlled output can make caller-side processing expensive.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/return-data-griefing/",
      "json": "https://ethertools.xyz/api/v1/lessons/return-data-griefing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/return-data-griefing/index.md"
    },
    {
      "slug": "evm-precompiles",
      "title": "Precompiles in the EVM",
      "summary": "Special addresses can expose protocol-defined computation.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/evm-precompiles/",
      "json": "https://ethertools.xyz/api/v1/lessons/evm-precompiles.json",
      "markdown": "https://ethertools.xyz/markdown/learn/evm-precompiles/index.md"
    },
    {
      "slug": "selfdestruct-changes",
      "title": "SELFDESTRUCT after protocol changes",
      "summary": "Historical deletion assumptions do not describe every modern case.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/selfdestruct-changes/",
      "json": "https://ethertools.xyz/api/v1/lessons/selfdestruct-changes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/selfdestruct-changes/index.md"
    },
    {
      "slug": "code-deployment-limits",
      "title": "Code size and deployment limits",
      "summary": "Runtime size, init-code size and execution gas are separate constraints.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/code-deployment-limits/",
      "json": "https://ethertools.xyz/api/v1/lessons/code-deployment-limits.json",
      "markdown": "https://ethertools.xyz/markdown/learn/code-deployment-limits/index.md"
    },
    {
      "slug": "frame-reentrancy",
      "title": "Reentrancy across call frames",
      "summary": "An external handoff can lead back into unfinished application logic.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/frame-reentrancy/",
      "json": "https://ethertools.xyz/api/v1/lessons/frame-reentrancy.json",
      "markdown": "https://ethertools.xyz/markdown/learn/frame-reentrancy/index.md"
    },
    {
      "slug": "rollback-boundaries",
      "title": "State rollback boundaries",
      "summary": "A child failure and a top-level failure have different enclosing scopes.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/rollback-boundaries/",
      "json": "https://ethertools.xyz/api/v1/lessons/rollback-boundaries.json",
      "markdown": "https://ethertools.xyz/markdown/learn/rollback-boundaries/index.md"
    },
    {
      "slug": "static-context",
      "title": "Static context restrictions",
      "summary": "Read-only execution rules extend across nested execution.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/static-context/",
      "json": "https://ethertools.xyz/api/v1/lessons/static-context.json",
      "markdown": "https://ethertools.xyz/markdown/learn/static-context/index.md"
    },
    {
      "slug": "delegatecall-trace",
      "title": "Inspect a delegatecall trace",
      "summary": "Track code source and state owner as separate columns.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/delegatecall-trace/",
      "json": "https://ethertools.xyz/api/v1/lessons/delegatecall-trace.json",
      "markdown": "https://ethertools.xyz/markdown/learn/delegatecall-trace/index.md"
    },
    {
      "slug": "failed-token-trace",
      "title": "Trace a failed token transfer",
      "summary": "Separate the call result, return value and state effects.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/failed-token-trace/",
      "json": "https://ethertools.xyz/api/v1/lessons/failed-token-trace.json",
      "markdown": "https://ethertools.xyz/markdown/learn/failed-token-trace/index.md"
    },
    {
      "slug": "proxy-fallback-trace",
      "title": "Trace proxy fallback execution",
      "summary": "A fallback can forward input and return the delegated outcome.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/proxy-fallback-trace/",
      "json": "https://ethertools.xyz/api/v1/lessons/proxy-fallback-trace.json",
      "markdown": "https://ethertools.xyz/markdown/learn/proxy-fallback-trace/index.md"
    },
    {
      "slug": "low-level-challenges",
      "title": "Low-level trace challenge set",
      "summary": "Explain context, outcome and surviving effects together.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/low-level-challenges/",
      "json": "https://ethertools.xyz/api/v1/lessons/low-level-challenges.json",
      "markdown": "https://ethertools.xyz/markdown/learn/low-level-challenges/index.md"
    },
    {
      "slug": "hashing",
      "title": "Hashes: fingerprints for data",
      "summary": "The same input gives the same fingerprint; a tiny edit changes it.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/hashing/",
      "json": "https://ethertools.xyz/api/v1/lessons/hashing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/hashing/index.md"
    },
    {
      "slug": "signatures",
      "title": "Signatures and permissions",
      "summary": "Prove authorization without sharing the secret that creates it.",
      "level": "advanced",
      "minutes": 7,
      "url": "https://ethertools.xyz/learn/signatures/",
      "json": "https://ethertools.xyz/api/v1/lessons/signatures.json",
      "markdown": "https://ethertools.xyz/markdown/learn/signatures/index.md"
    },
    {
      "slug": "bytes-hex",
      "title": "Bytes versus hexadecimal display",
      "summary": "Hex text is a way to write bytes, not automatically the bytes themselves.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/bytes-hex/",
      "json": "https://ethertools.xyz/api/v1/lessons/bytes-hex.json",
      "markdown": "https://ethertools.xyz/markdown/learn/bytes-hex/index.md"
    },
    {
      "slug": "keccak-sha3",
      "title": "Keccak-256 versus SHA3-256",
      "summary": "Similar names do not make two digest algorithms interchangeable.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/keccak-sha3/",
      "json": "https://ethertools.xyz/api/v1/lessons/keccak-sha3.json",
      "markdown": "https://ethertools.xyz/markdown/learn/keccak-sha3/index.md"
    },
    {
      "slug": "preimages-collisions",
      "title": "Hash preimages and collisions",
      "summary": "Finding an input for a digest differs from finding two matching digests.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/preimages-collisions/",
      "json": "https://ethertools.xyz/api/v1/lessons/preimages-collisions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/preimages-collisions/index.md"
    },
    {
      "slug": "domain-separation",
      "title": "Domain separation explained",
      "summary": "Bind a digest to the intended protocol context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/domain-separation/",
      "json": "https://ethertools.xyz/api/v1/lessons/domain-separation.json",
      "markdown": "https://ethertools.xyz/markdown/learn/domain-separation/index.md"
    },
    {
      "slug": "elliptic-curves",
      "title": "Elliptic curve intuition",
      "summary": "A public key is derived through a one-way group operation.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/elliptic-curves/",
      "json": "https://ethertools.xyz/api/v1/lessons/elliptic-curves.json",
      "markdown": "https://ethertools.xyz/markdown/learn/elliptic-curves/index.md"
    },
    {
      "slug": "secp256k1-keys",
      "title": "secp256k1 keys at a glance",
      "summary": "Ethereum EOA signing uses a specific curve and valid scalar range.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/secp256k1-keys/",
      "json": "https://ethertools.xyz/api/v1/lessons/secp256k1-keys.json",
      "markdown": "https://ethertools.xyz/markdown/learn/secp256k1-keys/index.md"
    },
    {
      "slug": "address-derivation",
      "title": "Ethereum address derivation",
      "summary": "An EOA address is derived from a public key, not directly from its display text.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/address-derivation/",
      "json": "https://ethertools.xyz/api/v1/lessons/address-derivation.json",
      "markdown": "https://ethertools.xyz/markdown/learn/address-derivation/index.md"
    },
    {
      "slug": "signature-rsv",
      "title": "Signature r, s and v fields",
      "summary": "Signature components need a stated encoding and signing context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/signature-rsv/",
      "json": "https://ethertools.xyz/api/v1/lessons/signature-rsv.json",
      "markdown": "https://ethertools.xyz/markdown/learn/signature-rsv/index.md"
    },
    {
      "slug": "recover-signer",
      "title": "Recovering an externally owned signer",
      "summary": "Recovery identifies a candidate signer for one digest and signature.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/recover-signer/",
      "json": "https://ethertools.xyz/api/v1/lessons/recover-signer.json",
      "markdown": "https://ethertools.xyz/markdown/learn/recover-signer/index.md"
    },
    {
      "slug": "personal-sign-prefix",
      "title": "Personal message signing prefixes",
      "summary": "Personal-message hashing prefixes the exact message length and bytes.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/personal-sign-prefix/",
      "json": "https://ethertools.xyz/api/v1/lessons/personal-sign-prefix.json",
      "markdown": "https://ethertools.xyz/markdown/learn/personal-sign-prefix/index.md"
    },
    {
      "slug": "eip712-domain",
      "title": "EIP-712 domain separators",
      "summary": "Typed signing binds structured content to a specified domain.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/eip712-domain/",
      "json": "https://ethertools.xyz/api/v1/lessons/eip712-domain.json",
      "markdown": "https://ethertools.xyz/markdown/learn/eip712-domain/index.md"
    },
    {
      "slug": "eip712-structs",
      "title": "EIP-712 typed structs",
      "summary": "Type definitions participate in the signed digest.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/eip712-structs/",
      "json": "https://ethertools.xyz/api/v1/lessons/eip712-structs.json",
      "markdown": "https://ethertools.xyz/markdown/learn/eip712-structs/index.md"
    },
    {
      "slug": "signature-nonces",
      "title": "Nonces and replay protection",
      "summary": "A valid authorization may need to be usable only once.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/signature-nonces/",
      "json": "https://ethertools.xyz/api/v1/lessons/signature-nonces.json",
      "markdown": "https://ethertools.xyz/markdown/learn/signature-nonces/index.md"
    },
    {
      "slug": "signature-deadlines",
      "title": "Deadlines and signature expiry",
      "summary": "Expiry is enforced by verification logic, not by the bytes aging automatically.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/signature-deadlines/",
      "json": "https://ethertools.xyz/api/v1/lessons/signature-deadlines.json",
      "markdown": "https://ethertools.xyz/markdown/learn/signature-deadlines/index.md"
    },
    {
      "slug": "erc1271-signatures",
      "title": "ERC-1271 contract signatures",
      "summary": "A contract account can validate signatures under its own policy.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/erc1271-signatures/",
      "json": "https://ethertools.xyz/api/v1/lessons/erc1271-signatures.json",
      "markdown": "https://ethertools.xyz/markdown/learn/erc1271-signatures/index.md"
    },
    {
      "slug": "signature-malleability",
      "title": "Malleability and signature normalization",
      "summary": "Different signature encodings can relate to the same authorization.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/signature-malleability/",
      "json": "https://ethertools.xyz/api/v1/lessons/signature-malleability.json",
      "markdown": "https://ethertools.xyz/markdown/learn/signature-malleability/index.md"
    },
    {
      "slug": "commit-reveal",
      "title": "Commit and reveal patterns",
      "summary": "Commit to a choice before exposing the choice and salt.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/commit-reveal/",
      "json": "https://ethertools.xyz/api/v1/lessons/commit-reveal.json",
      "markdown": "https://ethertools.xyz/markdown/learn/commit-reveal/index.md"
    },
    {
      "slug": "signature-practice",
      "title": "Signature verification practice set",
      "summary": "Check digest construction, account policy and replay rules together.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/signature-practice/",
      "json": "https://ethertools.xyz/api/v1/lessons/signature-practice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/signature-practice/index.md"
    },
    {
      "slug": "merkle-trees",
      "title": "Merkle trees and proofs",
      "summary": "Prove that one item belongs to a set using a short path of hashes.",
      "level": "advanced",
      "minutes": 8,
      "url": "https://ethertools.xyz/learn/merkle-trees/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-trees.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-trees/index.md"
    },
    {
      "slug": "merkle-leaf-hash",
      "title": "Hash a Merkle leaf",
      "summary": "The leaf encoding is part of the tree definition.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/merkle-leaf-hash/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-leaf-hash.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-leaf-hash/index.md"
    },
    {
      "slug": "merkle-pair-hash",
      "title": "Hash a pair of nodes",
      "summary": "Combine two fixed-width digests under an explicit rule.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/merkle-pair-hash/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-pair-hash.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-pair-hash/index.md"
    },
    {
      "slug": "merkle-pair-order",
      "title": "Sorted pairs versus ordered pairs",
      "summary": "Position-sensitive and commutative trees require different proof rules.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/merkle-pair-order/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-pair-order.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-pair-order/index.md"
    },
    {
      "slug": "merkle-odd-leaves",
      "title": "Odd leaf construction choices",
      "summary": "An unmatched node needs a documented construction rule.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/merkle-odd-leaves/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-odd-leaves.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-odd-leaves/index.md"
    },
    {
      "slug": "build-merkle-proof",
      "title": "Build a membership proof",
      "summary": "Collect the sibling needed at each step toward the root.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/build-merkle-proof/",
      "json": "https://ethertools.xyz/api/v1/lessons/build-merkle-proof.json",
      "markdown": "https://ethertools.xyz/markdown/learn/build-merkle-proof/index.md"
    },
    {
      "slug": "verify-merkle-proof",
      "title": "Verify a membership proof",
      "summary": "Recompute the path and compare it with the accepted root.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/verify-merkle-proof/",
      "json": "https://ethertools.xyz/api/v1/lessons/verify-merkle-proof.json",
      "markdown": "https://ethertools.xyz/markdown/learn/verify-merkle-proof/index.md"
    },
    {
      "slug": "proof-size-depth",
      "title": "Proof size and tree depth",
      "summary": "Balanced binary trees provide logarithmic-sized membership paths.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/proof-size-depth/",
      "json": "https://ethertools.xyz/api/v1/lessons/proof-size-depth.json",
      "markdown": "https://ethertools.xyz/markdown/learn/proof-size-depth/index.md"
    },
    {
      "slug": "trusted-merkle-root",
      "title": "Why a trusted root matters",
      "summary": "A proof is only as relevant as the root it is checked against.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/trusted-merkle-root/",
      "json": "https://ethertools.xyz/api/v1/lessons/trusted-merkle-root.json",
      "markdown": "https://ethertools.xyz/markdown/learn/trusted-merkle-root/index.md"
    },
    {
      "slug": "merkle-multiproofs",
      "title": "Multiproofs at a glance",
      "summary": "Several leaves can share intermediate reconstruction work.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/merkle-multiproofs/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-multiproofs.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-multiproofs/index.md"
    },
    {
      "slug": "merkle-allowlists",
      "title": "Merkle allowlists explained",
      "summary": "A contract can check membership without storing every entry individually.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/merkle-allowlists/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-allowlists.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-allowlists/index.md"
    },
    {
      "slug": "merkle-leaf-ambiguity",
      "title": "Leaf encoding ambiguity",
      "summary": "A secure digest cannot fix an ambiguous original encoding.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/merkle-leaf-ambiguity/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-leaf-ambiguity.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-leaf-ambiguity/index.md"
    },
    {
      "slug": "double-hashed-leaves",
      "title": "Double-hashed leaf conventions",
      "summary": "Some standard tree formats hash encoded leaves twice.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/double-hashed-leaves/",
      "json": "https://ethertools.xyz/api/v1/lessons/double-hashed-leaves.json",
      "markdown": "https://ethertools.xyz/markdown/learn/double-hashed-leaves/index.md"
    },
    {
      "slug": "tries-versus-merkle",
      "title": "Ethereum tries versus binary Merkle trees",
      "summary": "A simple binary playground is not an execution-state proof implementation.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/tries-versus-merkle/",
      "json": "https://ethertools.xyz/api/v1/lessons/tries-versus-merkle.json",
      "markdown": "https://ethertools.xyz/markdown/learn/tries-versus-merkle/index.md"
    },
    {
      "slug": "state-transaction-roots",
      "title": "State roots versus transaction roots",
      "summary": "Different roots commit to different parts of a block’s execution context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/state-transaction-roots/",
      "json": "https://ethertools.xyz/api/v1/lessons/state-transaction-roots.json",
      "markdown": "https://ethertools.xyz/markdown/learn/state-transaction-roots/index.md"
    },
    {
      "slug": "receipt-roots",
      "title": "Receipts roots explained",
      "summary": "Receipts have their own block commitment.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/receipt-roots/",
      "json": "https://ethertools.xyz/api/v1/lessons/receipt-roots.json",
      "markdown": "https://ethertools.xyz/markdown/learn/receipt-roots/index.md"
    },
    {
      "slug": "account-proofs",
      "title": "Account proofs at a glance",
      "summary": "A state proof connects an account record to an accepted state root.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/account-proofs/",
      "json": "https://ethertools.xyz/api/v1/lessons/account-proofs.json",
      "markdown": "https://ethertools.xyz/markdown/learn/account-proofs/index.md"
    },
    {
      "slug": "storage-proofs",
      "title": "Storage proofs at a glance",
      "summary": "Connect a slot claim through the account’s committed storage root.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/storage-proofs/",
      "json": "https://ethertools.xyz/api/v1/lessons/storage-proofs.json",
      "markdown": "https://ethertools.xyz/markdown/learn/storage-proofs/index.md"
    },
    {
      "slug": "verkle-direction",
      "title": "Verkle trees as a design direction",
      "summary": "Study a proposed commitment design without treating it as an activation promise.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/verkle-direction/",
      "json": "https://ethertools.xyz/api/v1/lessons/verkle-direction.json",
      "markdown": "https://ethertools.xyz/markdown/learn/verkle-direction/index.md"
    },
    {
      "slug": "merkle-challenges",
      "title": "Merkle proof challenge set",
      "summary": "Explain leaf encoding, path rules and root authority as one system.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/merkle-challenges/",
      "json": "https://ethertools.xyz/api/v1/lessons/merkle-challenges.json",
      "markdown": "https://ethertools.xyz/markdown/learn/merkle-challenges/index.md"
    },
    {
      "slug": "checks-effects-interactions",
      "title": "Checks, effects and interactions",
      "summary": "Make the relevant state consistent before handing control away.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/checks-effects-interactions/",
      "json": "https://ethertools.xyz/api/v1/lessons/checks-effects-interactions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/checks-effects-interactions/index.md"
    },
    {
      "slug": "reentrancy-counterexample",
      "title": "Reentrancy explained with a counterexample",
      "summary": "An unfinished withdrawal can expose an old entitlement to a callback.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/reentrancy-counterexample/",
      "json": "https://ethertools.xyz/api/v1/lessons/reentrancy-counterexample.json",
      "markdown": "https://ethertools.xyz/markdown/learn/reentrancy-counterexample/index.md"
    },
    {
      "slug": "cross-function-reentrancy",
      "title": "Cross-function reentrancy",
      "summary": "A callback can enter a different function sharing the same state.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/cross-function-reentrancy/",
      "json": "https://ethertools.xyz/api/v1/lessons/cross-function-reentrancy.json",
      "markdown": "https://ethertools.xyz/markdown/learn/cross-function-reentrancy/index.md"
    },
    {
      "slug": "read-only-reentrancy",
      "title": "Read-only reentrancy",
      "summary": "A callback can exploit an inconsistent observation without writing through a view function.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/read-only-reentrancy/",
      "json": "https://ethertools.xyz/api/v1/lessons/read-only-reentrancy.json",
      "markdown": "https://ethertools.xyz/markdown/learn/read-only-reentrancy/index.md"
    },
    {
      "slug": "access-control-errors",
      "title": "Access control mistakes",
      "summary": "Sensitive actions need the correct on-chain authority checks.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/access-control-errors/",
      "json": "https://ethertools.xyz/api/v1/lessons/access-control-errors.json",
      "markdown": "https://ethertools.xyz/markdown/learn/access-control-errors/index.md"
    },
    {
      "slug": "initializer-security",
      "title": "Uninitialized contracts and initializers",
      "summary": "An exposed setup function can become an unintended ownership path.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/initializer-security/",
      "json": "https://ethertools.xyz/api/v1/lessons/initializer-security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/initializer-security/index.md"
    },
    {
      "slug": "unchecked-arithmetic",
      "title": "Arithmetic checks and unchecked blocks",
      "summary": "Removing overflow checks requires a proved bound.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/unchecked-arithmetic/",
      "json": "https://ethertools.xyz/api/v1/lessons/unchecked-arithmetic.json",
      "markdown": "https://ethertools.xyz/markdown/learn/unchecked-arithmetic/index.md"
    },
    {
      "slug": "financial-rounding",
      "title": "Rounding direction in financial code",
      "summary": "Integer rounding can shift value between participants.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/financial-rounding/",
      "json": "https://ethertools.xyz/api/v1/lessons/financial-rounding.json",
      "markdown": "https://ethertools.xyz/markdown/learn/financial-rounding/index.md"
    },
    {
      "slug": "token-return-differences",
      "title": "ERC-20 return value differences",
      "summary": "Integration code must handle actual token call conventions.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/token-return-differences/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-return-differences.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-return-differences/index.md"
    },
    {
      "slug": "approval-races",
      "title": "Approval race conditions",
      "summary": "Replacing an allowance can interact with pending spending.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/approval-races/",
      "json": "https://ethertools.xyz/api/v1/lessons/approval-races.json",
      "markdown": "https://ethertools.xyz/markdown/learn/approval-races/index.md"
    },
    {
      "slug": "external-call-assumptions",
      "title": "Unsafe external call assumptions",
      "summary": "Targets can fail, reenter or return unexpected data.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/external-call-assumptions/",
      "json": "https://ethertools.xyz/api/v1/lessons/external-call-assumptions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/external-call-assumptions/index.md"
    },
    {
      "slug": "loop-denial-service",
      "title": "Denial of service in loops",
      "summary": "Unbounded work can make a required operation impossible to complete.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/loop-denial-service/",
      "json": "https://ethertools.xyz/api/v1/lessons/loop-denial-service.json",
      "markdown": "https://ethertools.xyz/markdown/learn/loop-denial-service/index.md"
    },
    {
      "slug": "storage-growth-security",
      "title": "Unbounded storage growth",
      "summary": "Persistent collections need a plan for future access costs.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/storage-growth-security/",
      "json": "https://ethertools.xyz/api/v1/lessons/storage-growth-security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/storage-growth-security/index.md"
    },
    {
      "slug": "timestamp-security",
      "title": "Timestamp dependence",
      "summary": "A block timestamp is a protocol input with boundary assumptions.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/timestamp-security/",
      "json": "https://ethertools.xyz/api/v1/lessons/timestamp-security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/timestamp-security/index.md"
    },
    {
      "slug": "randomness-security",
      "title": "Predictable randomness",
      "summary": "Public or influenceable inputs do not automatically form a fair draw.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/randomness-security/",
      "json": "https://ethertools.xyz/api/v1/lessons/randomness-security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/randomness-security/index.md"
    },
    {
      "slug": "oracle-manipulation",
      "title": "Oracle manipulation basics",
      "summary": "A quoted value is only as robust as its source and update rules.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/oracle-manipulation/",
      "json": "https://ethertools.xyz/api/v1/lessons/oracle-manipulation.json",
      "markdown": "https://ethertools.xyz/markdown/learn/oracle-manipulation/index.md"
    },
    {
      "slug": "flash-loan-mechanism",
      "title": "Flash loans as a mechanism",
      "summary": "Atomic borrowing changes available temporary capital, not arithmetic truth.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/flash-loan-mechanism/",
      "json": "https://ethertools.xyz/api/v1/lessons/flash-loan-mechanism.json",
      "markdown": "https://ethertools.xyz/markdown/learn/flash-loan-mechanism/index.md"
    },
    {
      "slug": "slippage-sandwich",
      "title": "Slippage and sandwich attacks",
      "summary": "Transaction ordering can worsen an execution price.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/slippage-sandwich/",
      "json": "https://ethertools.xyz/api/v1/lessons/slippage-sandwich.json",
      "markdown": "https://ethertools.xyz/markdown/learn/slippage-sandwich/index.md"
    },
    {
      "slug": "frontend-contract-security",
      "title": "Frontend security versus contract security",
      "summary": "A correct contract and a trustworthy interface are separate requirements.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/frontend-contract-security/",
      "json": "https://ethertools.xyz/api/v1/lessons/frontend-contract-security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/frontend-contract-security/index.md"
    },
    {
      "slug": "security-review-practice",
      "title": "Security review practice set",
      "summary": "Review authority, invariants and progress under hostile conditions.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/security-review-practice/",
      "json": "https://ethertools.xyz/api/v1/lessons/security-review-practice.json",
      "markdown": "https://ethertools.xyz/markdown/learn/security-review-practice/index.md"
    },
    {
      "slug": "delegate-storage-collisions",
      "title": "Delegatecall storage collisions",
      "summary": "Different slot interpretations can turn an ordinary write into corruption.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/delegate-storage-collisions/",
      "json": "https://ethertools.xyz/api/v1/lessons/delegate-storage-collisions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/delegate-storage-collisions/index.md"
    },
    {
      "slug": "proxy-authority-risks",
      "title": "Proxy admin and implementation risks",
      "summary": "Upgrade authority and application authority may be separate paths.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/proxy-authority-risks/",
      "json": "https://ethertools.xyz/api/v1/lessons/proxy-authority-risks.json",
      "markdown": "https://ethertools.xyz/markdown/learn/proxy-authority-risks/index.md"
    },
    {
      "slug": "upgrade-authorization",
      "title": "Upgrade authorization failures",
      "summary": "An upgrade path can bypass otherwise correct application permissions.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/upgrade-authorization/",
      "json": "https://ethertools.xyz/api/v1/lessons/upgrade-authorization.json",
      "markdown": "https://ethertools.xyz/markdown/learn/upgrade-authorization/index.md"
    },
    {
      "slug": "cross-chain-signature-replay",
      "title": "Signature replay across chains",
      "summary": "A message accepted on one chain may be accepted elsewhere without proper binding.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/cross-chain-signature-replay/",
      "json": "https://ethertools.xyz/api/v1/lessons/cross-chain-signature-replay.json",
      "markdown": "https://ethertools.xyz/markdown/learn/cross-chain-signature-replay/index.md"
    },
    {
      "slug": "typed-domain-mistakes",
      "title": "EIP-712 domain mistakes",
      "summary": "Signing and verification must agree on the intended domain fields.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/typed-domain-mistakes/",
      "json": "https://ethertools.xyz/api/v1/lessons/typed-domain-mistakes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/typed-domain-mistakes/index.md"
    },
    {
      "slug": "contract-signature-assumptions",
      "title": "ERC-1271 validation assumptions",
      "summary": "Contract-account approval can depend on current state and external calls.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/contract-signature-assumptions/",
      "json": "https://ethertools.xyz/api/v1/lessons/contract-signature-assumptions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/contract-signature-assumptions/index.md"
    },
    {
      "slug": "calldata-type-confusion",
      "title": "Calldata validation and type confusion",
      "summary": "Decodable bytes can still represent the wrong intended action.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/calldata-type-confusion/",
      "json": "https://ethertools.xyz/api/v1/lessons/calldata-type-confusion.json",
      "markdown": "https://ethertools.xyz/markdown/learn/calldata-type-confusion/index.md"
    },
    {
      "slug": "packed-encoding-collisions",
      "title": "abi.encodePacked collisions",
      "summary": "Variable-width concatenation can erase field boundaries.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/packed-encoding-collisions/",
      "json": "https://ethertools.xyz/api/v1/lessons/packed-encoding-collisions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/packed-encoding-collisions/index.md"
    },
    {
      "slug": "proof-leaf-security",
      "title": "Merkle proof leaf ambiguity",
      "summary": "Leaf and branch encodings need an unambiguous separation.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/proof-leaf-security/",
      "json": "https://ethertools.xyz/api/v1/lessons/proof-leaf-security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/proof-leaf-security/index.md"
    },
    {
      "slug": "callback-boundaries",
      "title": "Callback trust boundaries",
      "summary": "A callback is an entry point that needs its own authentication.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/callback-boundaries/",
      "json": "https://ethertools.xyz/api/v1/lessons/callback-boundaries.json",
      "markdown": "https://ethertools.xyz/markdown/learn/callback-boundaries/index.md"
    },
    {
      "slug": "token-hook-security",
      "title": "Token hook reentrancy",
      "summary": "A token interaction may invoke additional code.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/token-hook-security/",
      "json": "https://ethertools.xyz/api/v1/lessons/token-hook-security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/token-hook-security/index.md"
    },
    {
      "slug": "crosschain-authentication",
      "title": "Cross-chain message authentication",
      "summary": "A destination must validate origin and authorized sender, not just decode a payload.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/crosschain-authentication/",
      "json": "https://ethertools.xyz/api/v1/lessons/crosschain-authentication.json",
      "markdown": "https://ethertools.xyz/markdown/learn/crosschain-authentication/index.md"
    },
    {
      "slug": "bridge-replay",
      "title": "Bridge replay protection",
      "summary": "A previously accepted message must not unlock the same claim again.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/bridge-replay/",
      "json": "https://ethertools.xyz/api/v1/lessons/bridge-replay.json",
      "markdown": "https://ethertools.xyz/markdown/learn/bridge-replay/index.md"
    },
    {
      "slug": "accounting-invariants",
      "title": "Accounting invariants",
      "summary": "State the quantity that must remain conserved or bounded.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/accounting-invariants/",
      "json": "https://ethertools.xyz/api/v1/lessons/accounting-invariants.json",
      "markdown": "https://ethertools.xyz/markdown/learn/accounting-invariants/index.md"
    },
    {
      "slug": "donation-inflation",
      "title": "Donation and inflation attacks",
      "summary": "Unsolicited assets can change share-conversion ratios in some vault designs.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/donation-inflation/",
      "json": "https://ethertools.xyz/api/v1/lessons/donation-inflation.json",
      "markdown": "https://ethertools.xyz/markdown/learn/donation-inflation/index.md"
    },
    {
      "slug": "liquidation-boundaries",
      "title": "Liquidation edge cases",
      "summary": "Price, collateral and rounding boundaries jointly determine eligibility.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/liquidation-boundaries/",
      "json": "https://ethertools.xyz/api/v1/lessons/liquidation-boundaries.json",
      "markdown": "https://ethertools.xyz/markdown/learn/liquidation-boundaries/index.md"
    },
    {
      "slug": "decimal-precision-security",
      "title": "Precision loss across decimals",
      "summary": "Conversion order and rounding can destroy small values.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/decimal-precision-security/",
      "json": "https://ethertools.xyz/api/v1/lessons/decimal-precision-security.json",
      "markdown": "https://ethertools.xyz/markdown/learn/decimal-precision-security/index.md"
    },
    {
      "slug": "emergency-governance",
      "title": "Emergency controls and governance risk",
      "summary": "A protection mechanism also grants authority.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/emergency-governance/",
      "json": "https://ethertools.xyz/api/v1/lessons/emergency-governance.json",
      "markdown": "https://ethertools.xyz/markdown/learn/emergency-governance/index.md"
    },
    {
      "slug": "write-threat-model",
      "title": "Write a threat model",
      "summary": "Describe assets, actors and trust boundaries before listing attacks.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/write-threat-model/",
      "json": "https://ethertools.xyz/api/v1/lessons/write-threat-model.json",
      "markdown": "https://ethertools.xyz/markdown/learn/write-threat-model/index.md"
    },
    {
      "slug": "advanced-security-scenarios",
      "title": "Advanced security scenario set",
      "summary": "Combine multiple boundaries instead of checking each feature in isolation.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/advanced-security-scenarios/",
      "json": "https://ethertools.xyz/api/v1/lessons/advanced-security-scenarios.json",
      "markdown": "https://ethertools.xyz/markdown/learn/advanced-security-scenarios/index.md"
    },
    {
      "slug": "local-solidity-project",
      "title": "Set up a local Solidity project",
      "summary": "Keep source, compiler settings and tests together.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/local-solidity-project/",
      "json": "https://ethertools.xyz/api/v1/lessons/local-solidity-project.json",
      "markdown": "https://ethertools.xyz/markdown/learn/local-solidity-project/index.md"
    },
    {
      "slug": "compiler-errors",
      "title": "Read compiler errors",
      "summary": "Find the actual failing location before changing unrelated code.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/compiler-errors/",
      "json": "https://ethertools.xyz/api/v1/lessons/compiler-errors.json",
      "markdown": "https://ethertools.xyz/markdown/learn/compiler-errors/index.md"
    },
    {
      "slug": "counter-unit-tests",
      "title": "Unit tests for a counter",
      "summary": "Assert a small operation’s before-and-after behavior.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/counter-unit-tests/",
      "json": "https://ethertools.xyz/api/v1/lessons/counter-unit-tests.json",
      "markdown": "https://ethertools.xyz/markdown/learn/counter-unit-tests/index.md"
    },
    {
      "slug": "test-authorization",
      "title": "Test access control",
      "summary": "Exercise allowed callers and rejected callers.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/test-authorization/",
      "json": "https://ethertools.xyz/api/v1/lessons/test-authorization.json",
      "markdown": "https://ethertools.xyz/markdown/learn/test-authorization/index.md"
    },
    {
      "slug": "test-revert-payload",
      "title": "Test revert data",
      "summary": "Check the failure schema and state outcome.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/test-revert-payload/",
      "json": "https://ethertools.xyz/api/v1/lessons/test-revert-payload.json",
      "markdown": "https://ethertools.xyz/markdown/learn/test-revert-payload/index.md"
    },
    {
      "slug": "test-event-emission",
      "title": "Test event emission",
      "summary": "Verify emitter, topics, data and rollback behavior.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/test-event-emission/",
      "json": "https://ethertools.xyz/api/v1/lessons/test-event-emission.json",
      "markdown": "https://ethertools.xyz/markdown/learn/test-event-emission/index.md"
    },
    {
      "slug": "test-token-decimals",
      "title": "Test token decimals",
      "summary": "Keep raw integers and display scaling separate.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/test-token-decimals/",
      "json": "https://ethertools.xyz/api/v1/lessons/test-token-decimals.json",
      "markdown": "https://ethertools.xyz/markdown/learn/test-token-decimals/index.md"
    },
    {
      "slug": "test-storage-properties",
      "title": "Test storage invariants",
      "summary": "Check logical state properties across every modifying path.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/test-storage-properties/",
      "json": "https://ethertools.xyz/api/v1/lessons/test-storage-properties.json",
      "markdown": "https://ethertools.xyz/markdown/learn/test-storage-properties/index.md"
    },
    {
      "slug": "fuzz-testing",
      "title": "Fuzz testing explained",
      "summary": "Generate many inputs for a stated property.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/fuzz-testing/",
      "json": "https://ethertools.xyz/api/v1/lessons/fuzz-testing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fuzz-testing/index.md"
    },
    {
      "slug": "invariant-testing",
      "title": "Invariant testing explained",
      "summary": "Generate action sequences while checking a property after each step.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/invariant-testing/",
      "json": "https://ethertools.xyz/api/v1/lessons/invariant-testing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/invariant-testing/index.md"
    },
    {
      "slug": "abi-roundtrip-properties",
      "title": "Property-based ABI round trips",
      "summary": "Encoding and decoding should agree under the exact schema.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/abi-roundtrip-properties/",
      "json": "https://ethertools.xyz/api/v1/lessons/abi-roundtrip-properties.json",
      "markdown": "https://ethertools.xyz/markdown/learn/abi-roundtrip-properties/index.md"
    },
    {
      "slug": "fork-testing-limits",
      "title": "Fork testing and its limits",
      "summary": "A copied chain state is a particular test fixture, not a future guarantee.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/fork-testing-limits/",
      "json": "https://ethertools.xyz/api/v1/lessons/fork-testing-limits.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fork-testing-limits/index.md"
    },
    {
      "slug": "mocks-dependencies",
      "title": "Mocks versus real dependencies",
      "summary": "A mock tests selected behaviors, not every property of a real integration.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/mocks-dependencies/",
      "json": "https://ethertools.xyz/api/v1/lessons/mocks-dependencies.json",
      "markdown": "https://ethertools.xyz/markdown/learn/mocks-dependencies/index.md"
    },
    {
      "slug": "differential-testing",
      "title": "Differential testing",
      "summary": "Compare independent implementations on the same defined input.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/differential-testing/",
      "json": "https://ethertools.xyz/api/v1/lessons/differential-testing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/differential-testing/index.md"
    },
    {
      "slug": "gas-snapshots",
      "title": "Gas snapshots and their limits",
      "summary": "A measured cost belongs to a specific build and execution context.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/gas-snapshots/",
      "json": "https://ethertools.xyz/api/v1/lessons/gas-snapshots.json",
      "markdown": "https://ethertools.xyz/markdown/learn/gas-snapshots/index.md"
    },
    {
      "slug": "compiler-storage-output",
      "title": "Read compiler storage output",
      "summary": "Use slot, offset and type information together.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/compiler-storage-output/",
      "json": "https://ethertools.xyz/api/v1/lessons/compiler-storage-output.json",
      "markdown": "https://ethertools.xyz/markdown/learn/compiler-storage-output/index.md"
    },
    {
      "slug": "source-verification",
      "title": "Verify deployed source conceptually",
      "summary": "Reproduce the relevant compiled artifact under matching settings.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/source-verification/",
      "json": "https://ethertools.xyz/api/v1/lessons/source-verification.json",
      "markdown": "https://ethertools.xyz/markdown/learn/source-verification/index.md"
    },
    {
      "slug": "document-assumptions",
      "title": "Document contract assumptions",
      "summary": "Make hidden environmental requirements reviewable.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/document-assumptions/",
      "json": "https://ethertools.xyz/api/v1/lessons/document-assumptions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/document-assumptions/index.md"
    },
    {
      "slug": "review-code-change",
      "title": "Review a pull request for safety",
      "summary": "Connect a change to its affected invariants and authority.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/review-code-change/",
      "json": "https://ethertools.xyz/api/v1/lessons/review-code-change.json",
      "markdown": "https://ethertools.xyz/markdown/learn/review-code-change/index.md"
    },
    {
      "slug": "local-testing-capstone",
      "title": "A local-only testing capstone",
      "summary": "Build evidence for one small contract without using a public network.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/local-testing-capstone/",
      "json": "https://ethertools.xyz/api/v1/lessons/local-testing-capstone.json",
      "markdown": "https://ethertools.xyz/markdown/learn/local-testing-capstone/index.md"
    },
    {
      "slug": "execution-payloads",
      "title": "Execution payloads explained",
      "summary": "Execution data and consensus organization have different responsibilities.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/execution-payloads/",
      "json": "https://ethertools.xyz/api/v1/lessons/execution-payloads.json",
      "markdown": "https://ethertools.xyz/markdown/learn/execution-payloads/index.md"
    },
    {
      "slug": "block-header-fields",
      "title": "Block headers at a glance",
      "summary": "Headers summarize relationships and commitments rather than every underlying record.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/block-header-fields/",
      "json": "https://ethertools.xyz/api/v1/lessons/block-header-fields.json",
      "markdown": "https://ethertools.xyz/markdown/learn/block-header-fields/index.md"
    },
    {
      "slug": "typed-transactions",
      "title": "Transaction types and envelopes",
      "summary": "A type identifier selects the transaction payload format.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/typed-transactions/",
      "json": "https://ethertools.xyz/api/v1/lessons/typed-transactions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/typed-transactions/index.md"
    },
    {
      "slug": "eip155-replay",
      "title": "EIP-155 replay protection",
      "summary": "Legacy transaction signing can bind a chain identifier.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/eip155-replay/",
      "json": "https://ethertools.xyz/api/v1/lessons/eip155-replay.json",
      "markdown": "https://ethertools.xyz/markdown/learn/eip155-replay/index.md"
    },
    {
      "slug": "eip1559-fields",
      "title": "EIP-1559 transaction fields",
      "summary": "Fee caps express limits rather than a guaranteed paid price.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/eip1559-fields/",
      "json": "https://ethertools.xyz/api/v1/lessons/eip1559-fields.json",
      "markdown": "https://ethertools.xyz/markdown/learn/eip1559-fields/index.md"
    },
    {
      "slug": "access-list-transactions",
      "title": "Access list transactions",
      "summary": "Declared accesses participate in a specific transaction and gas model.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/access-list-transactions/",
      "json": "https://ethertools.xyz/api/v1/lessons/access-list-transactions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/access-list-transactions/index.md"
    },
    {
      "slug": "blob-transactions",
      "title": "Blob-carrying transactions",
      "summary": "Blob data availability and EVM calldata have different roles.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/blob-transactions/",
      "json": "https://ethertools.xyz/api/v1/lessons/blob-transactions.json",
      "markdown": "https://ethertools.xyz/markdown/learn/blob-transactions/index.md"
    },
    {
      "slug": "blob-commitments",
      "title": "Blob commitments at a glance",
      "summary": "A commitment binds data without placing every byte inside the reference.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/blob-commitments/",
      "json": "https://ethertools.xyz/api/v1/lessons/blob-commitments.json",
      "markdown": "https://ethertools.xyz/markdown/learn/blob-commitments/index.md"
    },
    {
      "slug": "state-transition-function",
      "title": "The state transition function",
      "summary": "Valid inputs transform one state into a defined next state.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/state-transition-function/",
      "json": "https://ethertools.xyz/api/v1/lessons/state-transition-function.json",
      "markdown": "https://ethertools.xyz/markdown/learn/state-transition-function/index.md"
    },
    {
      "slug": "account-state-fields",
      "title": "Account state fields",
      "summary": "Balance, nonce, code and storage commitments answer different questions.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/account-state-fields/",
      "json": "https://ethertools.xyz/api/v1/lessons/account-state-fields.json",
      "markdown": "https://ethertools.xyz/markdown/learn/account-state-fields/index.md"
    },
    {
      "slug": "account-transaction-nonce",
      "title": "Account nonce versus transaction nonce",
      "summary": "A submitted nonce is checked against the account’s execution state.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/account-transaction-nonce/",
      "json": "https://ethertools.xyz/api/v1/lessons/account-transaction-nonce.json",
      "markdown": "https://ethertools.xyz/markdown/learn/account-transaction-nonce/index.md"
    },
    {
      "slug": "fee-recipient",
      "title": "The fee recipient",
      "summary": "Execution rewards and burned fees have different destinations.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/fee-recipient/",
      "json": "https://ethertools.xyz/api/v1/lessons/fee-recipient.json",
      "markdown": "https://ethertools.xyz/markdown/learn/fee-recipient/index.md"
    },
    {
      "slug": "withdrawal-processing",
      "title": "Withdrawal processing basics",
      "summary": "Consensus-related withdrawals are not ordinary user-signed contract calls.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/withdrawal-processing/",
      "json": "https://ethertools.xyz/api/v1/lessons/withdrawal-processing.json",
      "markdown": "https://ethertools.xyz/markdown/learn/withdrawal-processing/index.md"
    },
    {
      "slug": "validator-lifecycle",
      "title": "Validator lifecycle overview",
      "summary": "Joining, participating, exiting and withdrawing are separate stages.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/validator-lifecycle/",
      "json": "https://ethertools.xyz/api/v1/lessons/validator-lifecycle.json",
      "markdown": "https://ethertools.xyz/markdown/learn/validator-lifecycle/index.md"
    },
    {
      "slug": "weak-subjectivity",
      "title": "Weak subjectivity explained",
      "summary": "A long-offline proof-of-stake node needs an appropriately trusted recent checkpoint.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/weak-subjectivity/",
      "json": "https://ethertools.xyz/api/v1/lessons/weak-subjectivity.json",
      "markdown": "https://ethertools.xyz/markdown/learn/weak-subjectivity/index.md"
    },
    {
      "slug": "finality-recovery",
      "title": "Finality failures and recovery",
      "summary": "Loss of finalization and conflicting finality are different conditions.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/finality-recovery/",
      "json": "https://ethertools.xyz/api/v1/lessons/finality-recovery.json",
      "markdown": "https://ethertools.xyz/markdown/learn/finality-recovery/index.md"
    },
    {
      "slug": "mev-incentives",
      "title": "MEV and proposer incentives",
      "summary": "Ordering and inclusion choices can affect economic outcomes.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/mev-incentives/",
      "json": "https://ethertools.xyz/api/v1/lessons/mev-incentives.json",
      "markdown": "https://ethertools.xyz/markdown/learn/mev-incentives/index.md"
    },
    {
      "slug": "proposer-builder-separation",
      "title": "Builder and proposer separation",
      "summary": "Constructing execution content and choosing a proposal can be separated.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/proposer-builder-separation/",
      "json": "https://ethertools.xyz/api/v1/lessons/proposer-builder-separation.json",
      "markdown": "https://ethertools.xyz/markdown/learn/proposer-builder-separation/index.md"
    },
    {
      "slug": "protocol-upgrades",
      "title": "Protocol upgrades and EIPs",
      "summary": "A proposal, reviewed specification and activated rule are different stages.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/protocol-upgrades/",
      "json": "https://ethertools.xyz/api/v1/lessons/protocol-upgrades.json",
      "markdown": "https://ethertools.xyz/markdown/learn/protocol-upgrades/index.md"
    },
    {
      "slug": "protocol-reading-challenge",
      "title": "Protocol reading challenge set",
      "summary": "Identify the rule, its context and the evidence required for a claim.",
      "level": "advanced",
      "minutes": 4,
      "url": "https://ethertools.xyz/learn/protocol-reading-challenge/",
      "json": "https://ethertools.xyz/api/v1/lessons/protocol-reading-challenge.json",
      "markdown": "https://ethertools.xyz/markdown/learn/protocol-reading-challenge/index.md"
    },
    {
      "slug": "capstone-transfer-explainer",
      "title": "Design a beginner-friendly transfer explainer",
      "summary": "Teach a first-time learner the path from intent to finality.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-transfer-explainer/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-transfer-explainer.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-transfer-explainer/index.md"
    },
    {
      "slug": "capstone-unit-converter",
      "title": "Build an exact unit converter",
      "summary": "Preserve every digit through ETH, Gwei and Wei conversions.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-unit-converter/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-unit-converter.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-unit-converter/index.md"
    },
    {
      "slug": "capstone-checksum",
      "title": "Build an address checksum checker",
      "summary": "Validate byte length and explain what a checksum does.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-checksum/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-checksum.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-checksum/index.md"
    },
    {
      "slug": "capstone-selector",
      "title": "Build a function selector calculator",
      "summary": "Derive the first four digest bytes from a canonical signature.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-selector/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-selector.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-selector/index.md"
    },
    {
      "slug": "capstone-transfer-bytes",
      "title": "Encode a token transfer by hand",
      "summary": "Assemble one selector and two full argument words.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-transfer-bytes/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-transfer-bytes.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-transfer-bytes/index.md"
    },
    {
      "slug": "capstone-dynamic-call",
      "title": "Decode a dynamic string call",
      "summary": "Follow the tuple-relative pointer before reading UTF-8 content.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-dynamic-call/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-dynamic-call.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-dynamic-call/index.md"
    },
    {
      "slug": "capstone-transfer-receipt",
      "title": "Decode a complete Transfer receipt",
      "summary": "Place a decoded log inside its emitter and receipt context.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-transfer-receipt/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-transfer-receipt.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-transfer-receipt/index.md"
    },
    {
      "slug": "capstone-execution-fee",
      "title": "Build a manual execution fee calculator",
      "summary": "Calculate a defined fee component from supplied inputs.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-execution-fee/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-execution-fee.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-execution-fee/index.md"
    },
    {
      "slug": "capstone-storage-visualizer",
      "title": "Build a storage packing visualizer",
      "summary": "Make slot boundaries and low-order offsets visible.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-storage-visualizer/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-storage-visualizer.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-storage-visualizer/index.md"
    },
    {
      "slug": "capstone-mapping-slot",
      "title": "Compute an address mapping slot",
      "summary": "Hash the full padded key and declared base slot.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-mapping-slot/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-mapping-slot.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-mapping-slot/index.md"
    },
    {
      "slug": "capstone-merkle-proof",
      "title": "Build and verify a Merkle proof",
      "summary": "Reproduce a complete four-leaf membership path.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-merkle-proof/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-merkle-proof.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-merkle-proof/index.md"
    },
    {
      "slug": "capstone-revert-decoder",
      "title": "Decode standard and custom reverts",
      "summary": "Choose a schema before interpreting failure bytes.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-revert-decoder/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-revert-decoder.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-revert-decoder/index.md"
    },
    {
      "slug": "capstone-stack-trace",
      "title": "Trace a tiny stack program",
      "summary": "Decode immediate bytes and record each stack transition.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-stack-trace/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-stack-trace.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-stack-trace/index.md"
    },
    {
      "slug": "capstone-signature-review",
      "title": "Review a signature permission request",
      "summary": "Explain exactly which action the signer would authorize.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-signature-review/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-signature-review.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-signature-review/index.md"
    },
    {
      "slug": "capstone-approval-threat-model",
      "title": "Threat-model a token approval flow",
      "summary": "Follow permission from the interface to later spending.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-approval-threat-model/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-approval-threat-model.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-approval-threat-model/index.md"
    },
    {
      "slug": "capstone-rollup-explainer",
      "title": "Explain a rollup to a new learner",
      "summary": "Separate execution, data availability and settlement assumptions.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-rollup-explainer/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-rollup-explainer.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-rollup-explainer/index.md"
    },
    {
      "slug": "capstone-upgrade-review",
      "title": "Review an upgrade storage change",
      "summary": "Preserve old state meaning while reviewing new authority.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-upgrade-review/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-upgrade-review.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-upgrade-review/index.md"
    },
    {
      "slug": "capstone-safe-sandbox",
      "title": "Write a safe learning sandbox",
      "summary": "Make experiments useful without requiring real assets or secrets.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-safe-sandbox/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-safe-sandbox.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-safe-sandbox/index.md"
    },
    {
      "slug": "capstone-publish-lesson",
      "title": "Publish a source-linked technical lesson",
      "summary": "Pair simple wording with reproducible evidence and a precise reference.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-publish-lesson/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-publish-lesson.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-publish-lesson/index.md"
    },
    {
      "slug": "capstone-portfolio",
      "title": "Your Ethereum learning portfolio",
      "summary": "Connect your explanations, byte traces and local tools into a reviewable set.",
      "level": "advanced",
      "minutes": 6,
      "url": "https://ethertools.xyz/learn/capstone-portfolio/",
      "json": "https://ethertools.xyz/api/v1/lessons/capstone-portfolio.json",
      "markdown": "https://ethertools.xyz/markdown/learn/capstone-portfolio/index.md"
    }
  ],
  "tools": [
    {
      "slug": "wei-to-eth",
      "title": "Wei ↔ ETH converter",
      "description": "Convert between Wei, Gwei and ETH using exact integer arithmetic. Supports up to 18 decimal places for ETH and 9 for Gwei, with no price feed or network request.",
      "url": "https://ethertools.xyz/tools/wei-to-eth/"
    },
    {
      "slug": "abi-encoder",
      "title": "ABI encoder",
      "description": "Encode typed function arguments into Ethereum calldata. Try common ERC-20 functions, dynamic strings, or provide a custom Solidity function declaration and JSON arguments.",
      "url": "https://ethertools.xyz/tools/abi-encoder/"
    },
    {
      "slug": "calldata-decoder",
      "title": "Calldata decoder",
      "description": "Decode Ethereum function calldata with a supplied interface and inspect its selector, 32-byte argument words and decoded values. Works locally without querying signature databases.",
      "url": "https://ethertools.xyz/tools/calldata-decoder/"
    },
    {
      "slug": "keccak256",
      "title": "Keccak-256 hash tool",
      "description": "Calculate the Keccak-256 hash of UTF-8 text or hexadecimal bytes locally. Also inspect the first four bytes used as an Ethereum function selector.",
      "url": "https://ethertools.xyz/tools/keccak256/"
    },
    {
      "slug": "address-checker",
      "title": "Address checksum checker",
      "description": "Validate a 20-byte Ethereum address and calculate its EIP-55 checksum. This checks formatting only, not ownership, balances, network or recipient safety.",
      "url": "https://ethertools.xyz/tools/address-checker/"
    },
    {
      "slug": "gas-calculator",
      "title": "Gas fee calculator",
      "description": "Calculate an EIP-1559 execution fee from gas used, base fee, priority fee cap and maximum fee cap. Uses manual inputs only; this is not a live gas estimator.",
      "url": "https://ethertools.xyz/tools/gas-calculator/"
    },
    {
      "slug": "event-decoder",
      "title": "ERC-20 event decoder",
      "description": "Decode a standard non-anonymous ERC-20 Transfer event from its topics and data. No RPC call is made and no token decimals are assumed.",
      "url": "https://ethertools.xyz/tools/event-decoder/"
    },
    {
      "slug": "storage-layout",
      "title": "Storage layout visualizer",
      "description": "Visualize packing for a simple sequence of Solidity elementary value types. Inspect slot and byte offsets. Excludes structs, arrays, inheritance and mappings.",
      "url": "https://ethertools.xyz/tools/storage-layout/"
    },
    {
      "slug": "merkle-tree",
      "title": "Merkle tree playground",
      "description": "Build a local binary Merkle tree from UTF-8 items with Keccak-256 sorted pairs, promoted odd nodes, and interactive proof verification. Educational tree format, not an Ethereum state trie.",
      "url": "https://ethertools.xyz/tools/merkle-tree/"
    },
    {
      "slug": "revert-decoder",
      "title": "Revert data decoder",
      "description": "Decode standard Solidity revert data and custom errors from a supplied declaration. Handles Error(string), Panic(uint256) and ABI-encoded custom errors without network requests.",
      "url": "https://ethertools.xyz/tools/revert-decoder/"
    }
  ],
  "tracks": [
    {
      "id": "first-principles",
      "title": "Your first steps",
      "level": "beginner",
      "url": "https://ethertools.xyz/learn/tracks/first-principles/",
      "topics": [
        "What is a blockchain?",
        "What is Ethereum?",
        "What is a digital ledger?",
        "Why do computers need to agree?",
        "What makes a block a block?",
        "How are blocks linked?",
        "What is a transaction?",
        "What does decentralization mean?",
        "Who can use Ethereum?",
        "Who owns Ethereum?",
        "Ethereum versus the internet",
        "Ethereum versus Bitcoin",
        "What can a blockchain prove?",
        "What a blockchain cannot prove",
        "Public does not mean anonymous",
        "What is a network fee?",
        "What is an Ethereum account?",
        "Reading your first block explorer page",
        "A tour of the Ethereum ecosystem",
        "Your first blockchain knowledge check"
      ]
    },
    {
      "id": "money-and-units",
      "title": "Digital value and units",
      "level": "beginner",
      "url": "https://ethertools.xyz/learn/tracks/money-and-units/",
      "topics": [
        "ETH, Gwei and Wei",
        "What makes ETH different from tokens?",
        "Count a billion and a quintillion",
        "Convert ETH to Wei by hand",
        "Convert Wei to ETH by hand",
        "Why Ethereum uses whole numbers",
        "Why floating-point amounts can fail",
        "Read a very large integer",
        "What are token decimals?",
        "Display units versus raw units",
        "Add and subtract exact ETH amounts",
        "Rounding versus truncation",
        "Why a converter is not a price feed",
        "What does a token balance mean?",
        "Native transfers versus token transfers",
        "Total supply versus circulating supply",
        "What does burning mean?",
        "What does minting mean?",
        "Dust and very small balances",
        "Unit conversion practice set"
      ]
    },
    {
      "id": "wallet-basics",
      "title": "Wallets without mystery",
      "level": "beginner",
      "url": "https://ethertools.xyz/learn/tracks/wallet-basics/",
      "topics": [
        "Wallets, keys and addresses",
        "What a wallet actually stores",
        "What is a recovery phrase?",
        "A public key versus a private key",
        "A wallet address is not a username",
        "Software wallets and hardware wallets",
        "Watch-only wallets",
        "One recovery phrase, many accounts",
        "What is a derivation path?",
        "What is a contract wallet?",
        "What is a multisignature wallet?",
        "What does connecting a wallet allow?",
        "Disconnecting is not revoking approval",
        "What are wallet networks?",
        "Why balances differ across networks",
        "Read a wallet confirmation screen",
        "Understand a receive screen",
        "Copy addresses without shortcuts",
        "Backups and recovery basics",
        "Wallet safety knowledge check"
      ]
    },
    {
      "id": "safe-exploration",
      "title": "Explore safely",
      "level": "beginner",
      "url": "https://ethertools.xyz/learn/tracks/safe-exploration/",
      "topics": [
        "Stay safe while exploring",
        "Spot a fake support message",
        "Recognize a recovery phrase scam",
        "Address poisoning explained",
        "Clipboard replacement attacks",
        "Read a domain carefully",
        "Understand token approvals",
        "Unlimited allowances explained",
        "What is a malicious signature?",
        "Why an airdrop can be bait",
        "What a testnet is for",
        "Test ETH versus real ETH",
        "How to read a faucet warning",
        "Verify an address through two channels",
        "Why transactions are usually irreversible",
        "What a block explorer label does not prove",
        "Hardware wallets still need careful review",
        "Read-only practice habits",
        "Prepare a personal transaction checklist",
        "Safety scenario challenge"
      ]
    },
    {
      "id": "transactions-intro",
      "title": "From send to settlement",
      "level": "beginner",
      "url": "https://ethertools.xyz/learn/tracks/transactions-intro/",
      "topics": [
        "Follow a transaction",
        "Write a payment instruction",
        "What is a transaction hash?",
        "What is a nonce?",
        "Pending, confirmed and finalized",
        "What is a mempool?",
        "Who includes a transaction?",
        "Why a transaction may wait",
        "Why a transaction may fail",
        "What is a transaction receipt?",
        "Gas used versus gas limit",
        "The recipient versus the sender",
        "Transaction value versus fee",
        "Read a simple transfer receipt",
        "What happens after pressing send?",
        "What is a replacement transaction?",
        "What does canceling a transaction mean?",
        "What is a chain reorganization?",
        "A transaction journey illustrated",
        "Transaction basics knowledge check"
      ]
    },
    {
      "id": "contracts-intro",
      "title": "Meet smart contracts",
      "level": "beginner",
      "url": "https://ethertools.xyz/learn/tracks/contracts-intro/",
      "topics": [
        "Smart contracts, simply",
        "A counter as a contract",
        "Functions and arguments explained",
        "Reading a contract versus changing it",
        "What does contract state mean?",
        "Who can call a smart contract?",
        "A contract has an address too",
        "What is deployment?",
        "What is contract bytecode?",
        "What is verified source code?",
        "What an ABI describes",
        "What contracts cannot do alone",
        "What is an oracle?",
        "What is a permission check?",
        "What is an administrator key?",
        "Can a contract be upgraded?",
        "Why bugs can be expensive",
        "A vending machine analogy and its limits",
        "Walk through a pretend contract call",
        "Smart contract knowledge check"
      ]
    },
    {
      "id": "tokens-and-ownership",
      "title": "Tokens and digital ownership",
      "level": "intermediate",
      "url": "https://ethertools.xyz/learn/tracks/tokens-and-ownership/",
      "topics": [
        "Tokens, NFTs and allowances",
        "How ERC-20 balances are recorded",
        "Understand transfer and transferFrom",
        "Read an allowance",
        "Approve zero and allowance changes",
        "The ERC-20 decimals convention",
        "What makes an NFT unique?",
        "ERC-721 ownership and token IDs",
        "ERC-1155 multiple token types",
        "Metadata and token ownership differ",
        "Where NFT images can live",
        "Onchain versus offchain metadata",
        "What does a token standard guarantee?",
        "Why token names are not identities",
        "Wrapped ETH explained",
        "Stablecoin mechanisms at a glance",
        "Rebasing tokens explained",
        "Fee-on-transfer tokens explained",
        "Events versus actual token behavior",
        "Token interface practice set"
      ]
    },
    {
      "id": "fees-and-execution",
      "title": "Gas and execution fees",
      "level": "intermediate",
      "url": "https://ethertools.xyz/learn/tracks/fees-and-execution/",
      "topics": [
        "Gas without the guesswork",
        "Gas as a measure of work",
        "The 21,000 gas transfer example",
        "Gas limit versus block gas limit",
        "EIP-1559 in plain language",
        "Base fee explained",
        "Priority fee explained",
        "Maximum fee cap explained",
        "Calculate the effective gas price",
        "What happens to unused gas?",
        "What happens when gas runs out?",
        "Why a revert still costs gas",
        "Why estimates can be wrong",
        "Warm versus cold access overview",
        "Storage writes and gas",
        "Gas refunds and refund limits",
        "Execution fees versus blob fees",
        "Layer 2 fee components",
        "Build a manual fee budget",
        "Gas calculation practice set"
      ]
    },
    {
      "id": "networks-and-consensus",
      "title": "The network behind the screen",
      "level": "intermediate",
      "url": "https://ethertools.xyz/learn/tracks/networks-and-consensus/",
      "topics": [
        "Nodes and the shared state",
        "How Ethereum agrees",
        "Execution clients and consensus clients",
        "Nodes versus validators",
        "What does a full node verify?",
        "What an archive node retains",
        "Peer-to-peer networking basics",
        "What happens in a slot?",
        "What happens in an epoch?",
        "Block proposers explained",
        "Attestations explained",
        "Fork choice in plain language",
        "Checkpoints and finality",
        "Validator rewards and penalties",
        "What slashing means",
        "Why client diversity matters",
        "What a light client checks",
        "Trusting an RPC provider",
        "Read calls versus write transactions",
        "Network architecture knowledge check"
      ]
    },
    {
      "id": "scaling",
      "title": "Scaling and layer 2",
      "level": "intermediate",
      "url": "https://ethertools.xyz/learn/tracks/scaling/",
      "topics": [
        "Layer 2 and rollups",
        "Layer 1 versus layer 2",
        "What is a rollup batch?",
        "Optimistic rollups explained",
        "Validity rollups explained",
        "Fraud proofs and challenge periods",
        "Validity proofs and verification",
        "What is a sequencer?",
        "Sequencer availability and escape paths",
        "Settlement versus execution",
        "What is data availability?",
        "Blob data in plain language",
        "Bridges as separate risk systems",
        "Canonical bridges versus third-party bridges",
        "Deposits and withdrawals",
        "Why withdrawal timing differs",
        "What is a sidechain?",
        "Network IDs and chain IDs",
        "Compare scaling trust assumptions",
        "Layer 2 scenario practice"
      ]
    },
    {
      "id": "applications",
      "title": "How people use Ethereum",
      "level": "intermediate",
      "url": "https://ethertools.xyz/learn/tracks/applications/",
      "topics": [
        "DeFi without the hype",
        "Payments with Ethereum",
        "Stablecoins for everyday use",
        "Decentralized exchanges explained",
        "Liquidity pools explained",
        "Price impact versus slippage",
        "Lending and collateral",
        "Liquidation explained",
        "Interest rate models at a glance",
        "Oracles in financial apps",
        "DAOs and shared decisions",
        "Governance proposals and voting",
        "Voting power versus ownership",
        "Decentralized identity explained",
        "ENS names explained",
        "Public goods funding explained",
        "Digital collectibles beyond speculation",
        "Account abstraction for users",
        "Composability and shared risk",
        "Application risk knowledge check"
      ]
    },
    {
      "id": "solidity-foundations",
      "title": "Write and read Solidity",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/solidity-foundations/",
      "topics": [
        "Read your first Solidity contract",
        "A Solidity source file explained",
        "Pragma directives and compiler versions",
        "Contract declarations and constructors",
        "Boolean and integer types",
        "Signed versus unsigned integers",
        "Addresses and payable addresses",
        "Fixed bytes versus dynamic bytes",
        "Strings and UTF-8",
        "State variables versus local variables",
        "Functions and visibility",
        "View and pure functions",
        "Function parameters and return values",
        "Require, revert and assert",
        "Modifiers and access checks",
        "Events in a contract",
        "Custom errors in Solidity",
        "Interfaces and inheritance basics",
        "Receive and fallback functions",
        "Read a complete small contract"
      ]
    },
    {
      "id": "abi-core",
      "title": "ABI encoding foundations",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/abi-core/",
      "topics": [
        "ABI: the contract’s interface",
        "Trace calldata byte by byte",
        "Canonical function signatures",
        "Calculate a function selector",
        "Encode uint256 step by step",
        "Encode signed integers",
        "Encode an address word",
        "Encode a boolean word",
        "Encode bytes4 versus bytes32",
        "Static tuples explained",
        "Fixed-size arrays in the ABI",
        "ABI return values without selectors",
        "Decode multiple return values",
        "Function overloads and selectors",
        "The JSON ABI format",
        "Why ABI data is not self-describing",
        "Selector collisions explained",
        "ABI encoding versus packed encoding",
        "A complete ERC-20 calldata walkthrough",
        "Static ABI decoding challenge set"
      ]
    },
    {
      "id": "abi-dynamic",
      "title": "Dynamic ABI and nested layouts",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/abi-dynamic/",
      "topics": [
        "Head and tail encoding",
        "Understand relative offsets",
        "Encode one string",
        "Count UTF-8 bytes correctly",
        "Padding dynamic bytes",
        "Encode two dynamic arguments",
        "Encode a uint256 array",
        "Encode a string array",
        "Fixed arrays of dynamic values",
        "Dynamic arrays of static tuples",
        "Tuples containing strings",
        "Nested tuple offset bases",
        "Nested dynamic array walkthrough",
        "Empty strings and empty arrays",
        "Malformed offsets and decoding failures",
        "Bounds checks in ABI decoders",
        "ABI coder version behavior",
        "Cross-language encoding consistency",
        "Build a dynamic encoding trace",
        "Nested ABI challenge set"
      ]
    },
    {
      "id": "events-and-errors",
      "title": "Read logs and failures",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/events-and-errors/",
      "topics": [
        "Events, topics and logs",
        "Understand why a call reverted",
        "Compute an event signature hash",
        "Indexed versus non-indexed arguments",
        "Decode an ERC-20 Transfer event",
        "Decode an Approval event",
        "Anonymous events explained",
        "Indexed strings and hashed topics",
        "Logs inside a receipt",
        "Why reverted logs do not persist",
        "Event ordering in nested calls",
        "Decode Error(string)",
        "Decode Panic(uint256)",
        "Read arithmetic panic codes",
        "Decode a custom Solidity error",
        "Empty revert data explained",
        "Errors can be bubbled up",
        "Why revert bytes can be spoofed",
        "Link an error to a call frame",
        "Receipt and error challenge set"
      ]
    },
    {
      "id": "storage-and-memory",
      "title": "Storage, memory and layout",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/storage-and-memory/",
      "topics": [
        "Solidity storage slots",
        "The 32-byte storage word",
        "Pack adjacent value types",
        "Byte offsets and low-order alignment",
        "Struct storage layout",
        "Fixed array storage layout",
        "Dynamic array base slots",
        "Mapping entry slot calculations",
        "Nested mappings explained",
        "Mapping to a struct",
        "Short bytes and short strings in storage",
        "Long bytes and strings in storage",
        "Inheritance and storage ordering",
        "Storage layout and proxies",
        "Namespaced storage explained",
        "Memory expansion basics",
        "The free memory pointer",
        "Calldata versus memory copies",
        "Transient storage explained",
        "Storage layout challenge set"
      ]
    },
    {
      "id": "evm-core",
      "title": "Inside the EVM",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/evm-core/",
      "topics": [
        "Step inside the EVM",
        "Bytecode versus source code",
        "The program counter",
        "The 256-bit stack",
        "PUSH, DUP and SWAP",
        "ADD, MUL and modular arithmetic",
        "Signed arithmetic opcodes",
        "Bitwise AND, OR and XOR",
        "Shifts and byte extraction",
        "MLOAD and MSTORE",
        "SLOAD and SSTORE",
        "Calldata load and copy",
        "Return data and copying",
        "JUMP, JUMPI and JUMPDEST",
        "STOP, RETURN and REVERT",
        "CALL opcode basics",
        "STATICCALL explained",
        "DELEGATECALL and execution context",
        "LOG opcodes and topics",
        "Trace a small EVM program"
      ]
    },
    {
      "id": "evm-deeper",
      "title": "Execution traces and low-level calls",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/evm-deeper/",
      "topics": [
        "Transaction context versus call context",
        "msg.sender versus tx.origin",
        "msg.value in nested calls",
        "Contract creation with CREATE",
        "Deterministic creation with CREATE2",
        "Init code versus runtime code",
        "Value transfer and call failures",
        "Call depth and stack limits",
        "Gas forwarding and the 63/64 rule",
        "Return-data griefing explained",
        "Precompiles in the EVM",
        "SELFDESTRUCT after protocol changes",
        "Code size and deployment limits",
        "Reentrancy across call frames",
        "State rollback boundaries",
        "Static context restrictions",
        "Inspect a delegatecall trace",
        "Trace a failed token transfer",
        "Trace proxy fallback execution",
        "Low-level trace challenge set"
      ]
    },
    {
      "id": "crypto-primitives",
      "title": "Cryptography with intuition",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/crypto-primitives/",
      "topics": [
        "Hashes: fingerprints for data",
        "Signatures and permissions",
        "Bytes versus hexadecimal display",
        "Keccak-256 versus SHA3-256",
        "Hash preimages and collisions",
        "Domain separation explained",
        "Elliptic curve intuition",
        "secp256k1 keys at a glance",
        "Ethereum address derivation",
        "Signature r, s and v fields",
        "Recovering an externally owned signer",
        "Personal message signing prefixes",
        "EIP-712 domain separators",
        "EIP-712 typed structs",
        "Nonces and replay protection",
        "Deadlines and signature expiry",
        "ERC-1271 contract signatures",
        "Malleability and signature normalization",
        "Commit and reveal patterns",
        "Signature verification practice set"
      ]
    },
    {
      "id": "trees-and-proofs",
      "title": "Trees, roots and proofs",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/trees-and-proofs/",
      "topics": [
        "Merkle trees and proofs",
        "Hash a Merkle leaf",
        "Hash a pair of nodes",
        "Sorted pairs versus ordered pairs",
        "Odd leaf construction choices",
        "Build a membership proof",
        "Verify a membership proof",
        "Proof size and tree depth",
        "Why a trusted root matters",
        "Multiproofs at a glance",
        "Merkle allowlists explained",
        "Leaf encoding ambiguity",
        "Double-hashed leaf conventions",
        "Ethereum tries versus binary Merkle trees",
        "State roots versus transaction roots",
        "Receipts roots explained",
        "Account proofs at a glance",
        "Storage proofs at a glance",
        "Verkle trees as a design direction",
        "Merkle proof challenge set"
      ]
    },
    {
      "id": "contract-security",
      "title": "Smart contract security foundations",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/contract-security/",
      "topics": [
        "Checks, effects and interactions",
        "Reentrancy explained with a counterexample",
        "Cross-function reentrancy",
        "Read-only reentrancy",
        "Access control mistakes",
        "Uninitialized contracts and initializers",
        "Arithmetic checks and unchecked blocks",
        "Rounding direction in financial code",
        "ERC-20 return value differences",
        "Approval race conditions",
        "Unsafe external call assumptions",
        "Denial of service in loops",
        "Unbounded storage growth",
        "Timestamp dependence",
        "Predictable randomness",
        "Oracle manipulation basics",
        "Flash loans as a mechanism",
        "Slippage and sandwich attacks",
        "Frontend security versus contract security",
        "Security review practice set"
      ]
    },
    {
      "id": "security-deeper",
      "title": "Advanced security reasoning",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/security-deeper/",
      "topics": [
        "Delegatecall storage collisions",
        "Proxy admin and implementation risks",
        "Upgrade authorization failures",
        "Signature replay across chains",
        "EIP-712 domain mistakes",
        "ERC-1271 validation assumptions",
        "Calldata validation and type confusion",
        "abi.encodePacked collisions",
        "Merkle proof leaf ambiguity",
        "Callback trust boundaries",
        "Token hook reentrancy",
        "Cross-chain message authentication",
        "Bridge replay protection",
        "Accounting invariants",
        "Donation and inflation attacks",
        "Liquidation edge cases",
        "Precision loss across decimals",
        "Emergency controls and governance risk",
        "Write a threat model",
        "Advanced security scenario set"
      ]
    },
    {
      "id": "testing-and-building",
      "title": "Build, test and reason",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/testing-and-building/",
      "topics": [
        "Set up a local Solidity project",
        "Read compiler errors",
        "Unit tests for a counter",
        "Test access control",
        "Test revert data",
        "Test event emission",
        "Test token decimals",
        "Test storage invariants",
        "Fuzz testing explained",
        "Invariant testing explained",
        "Property-based ABI round trips",
        "Fork testing and its limits",
        "Mocks versus real dependencies",
        "Differential testing",
        "Gas snapshots and their limits",
        "Read compiler storage output",
        "Verify deployed source conceptually",
        "Document contract assumptions",
        "Review a pull request for safety",
        "A local-only testing capstone"
      ]
    },
    {
      "id": "protocol-deeper",
      "title": "Ethereum protocol concepts",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/protocol-deeper/",
      "topics": [
        "Execution payloads explained",
        "Block headers at a glance",
        "Transaction types and envelopes",
        "EIP-155 replay protection",
        "EIP-1559 transaction fields",
        "Access list transactions",
        "Blob-carrying transactions",
        "Blob commitments at a glance",
        "The state transition function",
        "Account state fields",
        "Account nonce versus transaction nonce",
        "The fee recipient",
        "Withdrawal processing basics",
        "Validator lifecycle overview",
        "Weak subjectivity explained",
        "Finality failures and recovery",
        "MEV and proposer incentives",
        "Builder and proposer separation",
        "Protocol upgrades and EIPs",
        "Protocol reading challenge set"
      ]
    },
    {
      "id": "capstones",
      "title": "Connect everything together",
      "level": "advanced",
      "url": "https://ethertools.xyz/learn/tracks/capstones/",
      "topics": [
        "Design a beginner-friendly transfer explainer",
        "Build an exact unit converter",
        "Build an address checksum checker",
        "Build a function selector calculator",
        "Encode a token transfer by hand",
        "Decode a dynamic string call",
        "Decode a complete Transfer receipt",
        "Build a manual execution fee calculator",
        "Build a storage packing visualizer",
        "Compute an address mapping slot",
        "Build and verify a Merkle proof",
        "Decode standard and custom reverts",
        "Trace a tiny stack program",
        "Review a signature permission request",
        "Threat-model a token approval flow",
        "Explain a rollup to a new learner",
        "Review an upgrade storage change",
        "Write a safe learning sandbox",
        "Publish a source-linked technical lesson",
        "Your Ethereum learning portfolio"
      ]
    }
  ]
}
