Skip to content

Medium Blockchain Interview Questions

98 medium questions with answers. Applied questions that check whether you can use the concepts on real work.

Topics in the medium set

Consensus and Scaling: 15 Solidity Programming: 14 Blockchain Fundamentals: 13 Smart Contract Security: 13 Cryptography for Blockchain: 12 Ethereum and the EVM: 11 dApp Development: 11 DeFi, Tokens and NFTs: 9
Solved — mediumStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What is the difference between a full node, a light node and an archive node?

Save to ▾
Show answer
A full node downloads and validates every block and keeps the current state, so it can verify everything independently. A light node stores only block headers and asks full nodes for Merkle proofs of the data it needs, which suits mobile wallets. An archive node keeps all historical states, so you can query a balance at any past block; indexers and block explorers need it, but it requires many terabytes of storage.
02

What is double spending and how does a blockchain prevent it?

Save to ▾
Show answer
Double spending is trying to spend the same digital money twice, for example sending the same coins to two merchants. A blockchain prevents it by keeping one shared ordering of transactions agreed through consensus. Once a transaction is included in a block, any conflicting transaction that spends the same funds is rejected as invalid. Merchants wait for several confirmations so that the chance of the block being replaced in a reorg becomes negligible.
03

Compare the UTXO model and the account model.

Save to ▾
Show answer
In the UTXO model used by Bitcoin, coins exist as unspent transaction outputs; a transaction consumes some outputs and creates new ones, which makes parallel validation and privacy easier. In the account model used by Ethereum, the state stores a balance and nonce per account, which is simpler for smart contracts and wallets. The trade-off: UTXO avoids replay issues and scales verification well, while accounts make complex stateful logic far easier to write.
04

What is the difference between a soft fork and a hard fork?

Save to ▾
Show answer
A soft fork tightens the rules so that new blocks are still valid for old nodes; it is backward compatible, like Bitcoin's SegWit upgrade. A hard fork changes the rules so that old nodes reject new blocks, so every node must upgrade or the chain splits, as with Ethereum and Ethereum Classic in 2016. Planned network upgrades on Ethereum, such as Dencun and Pectra, are coordinated hard forks that all clients adopt together.
05

What is the blockchain trilemma?

Save to ▾
Show answer
The trilemma says a blockchain finds it hard to maximise decentralisation, security and scalability at the same time on a single layer. Raising block size or using few validators increases throughput but reduces decentralisation. Ethereum's answer is a rollup-centric roadmap: keep the base layer decentralised and secure, and move execution to Layer 2 rollups that post data back to Layer 1. Many high-throughput chains instead accept fewer, more powerful validators.
06

What is a mempool?

Save to ▾
Show answer
The mempool is each node's waiting area for valid transactions that have been broadcast but not yet included in a block. Block producers usually pick transactions paying the highest fees or priority tips. Every node has its own mempool, so contents can differ slightly. Because pending transactions are public, bots can watch the mempool and front-run trades, which is why private transaction relays and order-flow auctions are used for sensitive transactions.
07

What are the main components of Hyperledger Fabric?

Save to ▾
Show answer
Hyperledger Fabric is a permissioned enterprise framework. Peers hold the ledger and run chaincode (smart contracts written in Go, Java or JavaScript). Orderers, usually using Raft, sequence transactions into blocks. A Membership Service Provider issues identities through certificate authorities. Channels give separate private ledgers to subsets of members, and private data collections hide data inside a channel. Fabric uses an execute-order-validate flow with endorsement policies instead of mining.
08

An HR team wants to store employee records on a blockchain. Would you recommend it?

Save to ▾
Show answer
Usually no. Employee records are owned by one organisation, change often and contain personal data that must be correctable and deletable under the DPDP Act 2023. A normal database with role-based access and audit logs is cheaper, faster and compliant. I would ask who else needs to trust the data. If several employers or background-check agencies must verify certificates, I would store only hashes of credentials on a permissioned chain and keep the actual data off-chain.
09

Design a blockchain solution for farm-to-store supply chain traceability. What goes on-chain?

Save to ▾
Show answer
I would use a permissioned or low-cost chain where farmers, transporters, warehouses and retailers are known members. On-chain I would record batch IDs, ownership handovers, timestamps, signer identity and hashes of certificates or sensor data. Large documents, images and IoT streams stay off-chain in object storage or IPFS, referenced by hash. QR codes on packs link consumers to the trail. The main risk is bad input data, so I would add signed device readings and audits.
10

A user's transaction has been pending for an hour. How do you troubleshoot it?

Save to ▾
Show answer
First check it on a block explorer: if it is not found, it was never broadcast. If pending, the fee is probably below current market rates, or an earlier transaction with a lower nonce is stuck and blocking it. On Ethereum you fix it by sending a replacement with the same nonce and a higher max fee and priority fee, or cancel by sending zero ETH to yourself with that nonce. Then make the wallet estimate fees dynamically.
11

Write a minimal Python example showing how blocks are linked by hashes.

Save to ▾
Show answer
Each block stores the previous hash, so changing any earlier data breaks the chain. import hashlib, json def block_hash(block): data = json.dumps(block, sort_keys=True).encode() return hashlib.sha256(data).hexdigest() chain = [{'index': 0, 'data': 'genesis', 'prev': '0'}] for i, tx in enumerate(['A pays B 5', 'B pays C 2'], 1): chain.append({'index': i, 'data': tx, 'prev': block_hash(chain[-1])}) valid = all(chain[i]['prev'] == block_hash(chain[i-1]) for i in range(1, len(chain))) print(valid)
12

How do you get the latest block number from an Ethereum node using JSON-RPC?

Save to ▾
Show answer
Send a JSON-RPC POST request to the node or provider URL. The result is a hex string that you convert to decimal. curl -s -X POST https://rpc.example.org \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' # Response: {"jsonrpc":"2.0","id":1,"result":"0x15d3a1c"} # In Python: int('0x15d3a1c', 16) Other common methods are eth_getBalance, eth_call and eth_getTransactionReceipt.
13

Tell me about a time you explained blockchain to a non-technical stakeholder.

Save to ▾
Show answer
Situation: a business head wanted 'blockchain' in a vendor portal because competitors mentioned it. Task: help him decide. Action: I compared it to a shared online spreadsheet that nobody can secretly edit, then showed cost, speed and privacy trade-offs against a normal database with audit logs. Result: we agreed to keep the portal on a database and anchor monthly hashes of invoices on a chain for proof, saving months of work while meeting the trust goal.
14

What is the difference between SHA-256 and Keccak-256?

Save to ▾
Show answer
SHA-256 is from the SHA-2 family and uses a Merkle-Damgard construction; Bitcoin uses double SHA-256 for block hashes and transaction IDs. Keccak-256 is based on the sponge construction and is what Ethereum uses for addresses, function selectors, event topics and storage slots. Ethereum's Keccak-256 is the original Keccak submission and differs from the final NIST SHA3-256 in padding, so the two give different outputs for the same input.
15

What is ECDSA and why does Ethereum use the secp256k1 curve?

Save to ▾
Show answer
ECDSA is the Elliptic Curve Digital Signature Algorithm. It gives strong security with short keys: a 256-bit key is roughly as strong as a 3072-bit RSA key, which keeps transactions small. Bitcoin and Ethereum use the secp256k1 curve, whose simple structure allows efficient computation. A signature has values r and s plus a recovery id v, which lets nodes recover the signer's public key from the signature, so the sender address need not be included separately.
16

How is an Ethereum address derived from a private key?

Save to ▾
Show answer
Start with a random 256-bit private key. Multiply it by the secp256k1 generator point to get a 64-byte uncompressed public key. Take the Keccak-256 hash of that public key and keep the last 20 bytes; that is the address, shown as 0x plus 40 hex characters. EIP-55 adds a mixed-case checksum so typos can be detected. The process is one-way: you cannot get the private key back from the address or public key.
17

What is a Merkle tree and what is a Merkle proof?

Save to ▾
Show answer
A Merkle tree hashes data items in pairs, level by level, until one root hash remains. The root summarises all items: changing any item changes the root. A Merkle proof is the list of sibling hashes on the path from one item to the root. With it, a light client can prove that a transaction is in a block using about log2(n) hashes instead of downloading all transactions. Airdrop allowlists use the same trick on-chain.
18

What are seed phrases and HD wallets (BIP-39, BIP-32, BIP-44)?

Save to ▾
Show answer
BIP-39 encodes random entropy as a 12 or 24 word mnemonic, which is turned into a binary seed. BIP-32 defines hierarchical deterministic wallets that derive a tree of key pairs from that seed. BIP-44 standardises the derivation path, for example m/44'/60'/0'/0/0 for the first Ethereum account. So one backed-up seed phrase can restore unlimited addresses across chains. Whoever knows the phrase controls every derived account, so it must never be stored online.
19

Compare multisig wallets and MPC wallets.

Save to ▾
Show answer
A multisig wallet is a smart contract, such as a Safe, that needs M of N owner signatures to execute a transaction; rules are visible on-chain and easy to audit, but every action costs extra gas and works per chain. An MPC wallet splits one private key into shares held by different parties who jointly produce a normal signature; it looks like a regular address, works on any chain and allows key rotation, but the security depends on the off-chain implementation.
20

Users complain they must pay gas to approve tokens before every trade. How can signatures help?

Save to ▾
Show answer
Use off-chain signed approvals. With EIP-2612 permit, the user signs a typed EIP-712 message granting an allowance, and the dApp submits it with the trade in one transaction, so no separate approve call is needed. For tokens without permit, Permit2-style contracts give the same experience after one approval. EIP-712 shows readable fields in the wallet, reducing phishing risk. Always include a nonce, deadline, chain ID and verifying contract to prevent replays.
21

How would you check on-chain whether a user is in a 10,000-address allowlist without storing all addresses?

Save to ▾
Show answer
Build a Merkle tree off-chain from the allowlisted addresses (hashing each leaf, ideally double-hashed with amounts if needed) and store only the 32-byte root in the contract. Each user submits a proof of about 14 hashes for 10,000 leaves. The contract recomputes the root with OpenZeppelin MerkleProof.verify and compares it. This costs one storage slot instead of 10,000, and you can update the list by changing the root.
22

A developer accidentally pushed a private key to a public GitHub repo. What do you do?

Save to ▾
Show answer
Treat the key as compromised immediately, because bots scan GitHub within seconds. Move all funds and tokens to a new secure wallet, revoke token approvals, and if the key owns contracts, transfer ownership or roles to a new multisig. Removing the commit is not enough since history and forks keep it. Then rotate any related API keys, add secret scanning and pre-commit hooks, and load keys from environment variables or a secrets manager.
23

Show how to sign and verify a message with ethers.js.

Save to ▾
Show answer
With ethers v6, a wallet signs using EIP-191 personal sign, and verifyMessage recovers the address. import { Wallet, verifyMessage } from 'ethers'; const wallet = Wallet.createRandom(); const message = 'Login nonce: 48213'; const signature = await wallet.signMessage(message); const recovered = verifyMessage(message, signature); console.log(recovered === wallet.address); // true This pattern powers Sign-In with Ethereum; the server issues a fresh nonce each time to stop replay.
24

Write a Python function that computes a Merkle root from a list of transactions.

Save to ▾
Show answer
Hash leaves, then hash pairs until one remains, duplicating the last hash when a level is odd (Bitcoin style). import hashlib def h(b): return hashlib.sha256(b).digest() def merkle_root(txs): level = [h(t.encode()) for t in txs] while len(level) > 1: if len(level) % 2: level.append(level[-1]) level = [h(level[i] + level[i+1]) for i in range(0, len(level), 2)] return level[0].hex() print(merkle_root(['tx1', 'tx2', 'tx3']))
25

Describe a time you found a security problem in code and how you handled it.

Save to ▾
Show answer
Situation: while reviewing a teammate's staking contract, I saw it sent tokens before updating the user's balance. Task: confirm the risk without blaming anyone. Action: I wrote a Foundry test with a malicious receiver that re-entered withdraw and drained extra funds, then shared it privately with a suggested fix using checks-effects-interactions and a reentrancy guard. Result: the fix merged before the audit, and we added reentrancy tests to our standard checklist.
26

How does Ethereum's Proof of Stake work?

Save to ▾
Show answer
Validators deposit 32 ETH (after the Pectra upgrade a validator can hold up to 2048 ETH) to join. Time is divided into 12-second slots and 32-slot epochs. In each slot a randomly chosen validator proposes a block and committees attest to it. The fork-choice rule LMD-GHOST picks the head, and Casper FFG finalises checkpoints when two-thirds of stake agrees. Honest validators earn rewards; offline ones lose small amounts, and provably malicious ones are slashed.
27

What is slashing in Proof of Stake?

Save to ▾
Show answer
Slashing is a penalty that burns part of a validator's stake and forcibly exits it when it provably breaks protocol rules. On Ethereum the slashable offences are proposing two different blocks in the same slot and making conflicting or surrounding attestations. The penalty grows if many validators are slashed around the same time, which punishes coordinated attacks. Simply being offline is not slashing; it only causes small inactivity penalties. Running the same key on two machines is the most common cause.
28

What are Delegated Proof of Stake and Proof of Authority?

Save to ▾
Show answer
In Delegated Proof of Stake, token holders vote for a small set of block producers who validate on their behalf, giving high throughput but more centralisation. In Proof of Authority, a fixed set of known, reputable validators sign blocks; their identity, not stake, is at risk. PoA, often via Clique, IBFT or QBFT, suits private and consortium EVM networks and some testnets, where participants are known and fast, predictable block times matter more than open participation.
29

What is the difference between optimistic rollups and zk-rollups?

Save to ▾
Show answer
Optimistic rollups assume batches are valid and allow a challenge window, typically about seven days, during which anyone can submit a fraud proof; this makes them EVM-compatible and simpler but slows native withdrawals. Zk-rollups submit a validity proof with each batch, so L1 verifies correctness mathematically and withdrawals finalise once the proof is accepted. Zk proving is computationally heavy and EVM equivalence was harder, though zkEVMs have matured a lot by 2026.
30

How is a sidechain different from a rollup?

Save to ▾
Show answer
A sidechain is an independent blockchain with its own validators and consensus, connected to the main chain by a bridge. Its security depends on its own validator set, so if they collude, funds can be stolen. A rollup posts its transaction data and state roots to Ethereum and relies on fraud or validity proofs, so it inherits Layer 1 security for correctness. Sidechains are usually cheaper and more flexible, but rollups give stronger guarantees.
31

What are state channels, such as the Lightning Network?

Save to ▾
Show answer
A state channel locks funds in an on-chain contract or multisig between parties, who then exchange many signed off-chain updates and settle only the final state on-chain. Lightning on Bitcoin links channels into a network so payments route through intermediaries using hashed timelock contracts. Channels give instant, nearly free payments but need participants to be online or use watchtowers, and they lock liquidity, so they suit repeated payments between known parties rather than general smart contracts.
32

What is the difference between an execution client and a consensus client, and why does client diversity matter?

Save to ▾
Show answer
Since the Merge, an Ethereum node runs two pieces of software. The execution client, such as Geth, Nethermind, Besu, Erigon or Reth, runs the EVM, holds state and handles transactions. The consensus client, such as Lighthouse, Prysm, Teku, Nimbus or Lodestar, runs Proof of Stake. They talk over the Engine API. Client diversity matters because a bug in a client used by over two-thirds of validators could finalise an invalid chain and cause mass slashing.
33

Your dApp's users are paying high gas fees on Ethereum mainnet. How would you choose a Layer 2?

Save to ▾
Show answer
I would compare candidate rollups on security (proof system live, stage of decentralisation, upgrade keys), EVM compatibility so our Solidity code deploys unchanged, ecosystem fit (wallets, oracles, liquidity, bridges our users already use), fees and throughput, and withdrawal experience. I would deploy to testnets first, measure real costs and latency, and check that our dependencies such as Chainlink feeds exist there. Then migrate gradually, keeping L1 contracts for high-value settlement if needed.
34

A user is angry that withdrawing from an optimistic rollup to Ethereum takes seven days. How do you explain and solve it?

Save to ▾
Show answer
Explain that the seven-day window lets anyone challenge a fraudulent batch; it protects their funds. For faster exits, offer third-party fast bridges or intent-based bridges where a liquidity provider pays them on L1 within minutes for a small fee and later claims the slow withdrawal. Also show the expected timeline clearly in the UI and send a notification when funds are claimable, because most anger comes from uncertainty, not the delay itself.
35

Your staking validator is missing attestations and losing rewards. How do you investigate?

Save to ▾
Show answer
Check that both execution and consensus clients are synced and peering well, since low peer count or a lagging execution client causes missed duties. Look at system clock sync through NTP, CPU, memory and disk I/O, as slow disks often cause delays. Review client logs and metrics in Grafana, check for pending client upgrades before a fork, and verify network ports are open. Never start a second copy of the same validator key as a fix, because that causes slashing.
36

Write a simple Proof of Work loop in Python with a difficulty setting.

Save to ▾
Show answer
The miner increments the nonce until the hash starts with the required number of zero hex digits. import hashlib def mine(data, difficulty=4): prefix = '0' * difficulty nonce = 0 while True: h = hashlib.sha256(f'{data}{nonce}'.encode()).hexdigest() if h.startswith(prefix): return nonce, h nonce += 1 print(mine('block-1: A pays B 5')) Each extra zero makes mining about 16 times harder, while verifying still needs one hash.
37

How do you deploy a contract to a Layer 2 testnet with Foundry?

Save to ▾
Show answer
Set the RPC URL and a deployer key, then use forge create or a script, and verify the source on the explorer. export RPC_URL=https://sepolia.l2-example.org export PRIVATE_KEY=0x... # testnet key only forge create src/Counter.sol:Counter \ --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast # Scripted deploy with verification forge script script/Deploy.s.sol --rpc-url $RPC_URL \ --broadcast --verify Use a keystore via cast wallet import instead of raw keys for anything real.
38

How do you read the latest finalized block with ethers.js, and why use it?

Save to ▾
Show answer
Pass the block tag to getBlock. The finalized tag returns the latest block that Proof of Stake has finalised, which cannot be reverted without slashing a third of stake. import { JsonRpcProvider } from 'ethers'; const provider = new JsonRpcProvider(process.env.RPC_URL); const latest = await provider.getBlock('latest'); const safe = await provider.getBlock('safe'); const finalized = await provider.getBlock('finalized'); console.log(latest.number - finalized.number); // usually about 64-96 Use finalized for deposits and accounting; use latest for UI updates.
39

Tell me about a technical decision you made where you had to balance trade-offs.

Save to ▾
Show answer
Situation: our loyalty-points product needed on-chain points but users would not pay mainnet fees. Task: pick a chain. Action: I compared three rollups and a sidechain on fees, security model, wallet support and bridge maturity, built a quick benchmark, and wrote a one-page decision record with risks. Result: we chose a rollup with live fraud proofs, cut per-transaction cost by over 95 percent, and documented a migration path if our requirements changed.
40

Describe a time you disagreed with a teammate about architecture.

Save to ▾
Show answer
Situation: a teammate wanted our indexer to read every event directly from the node at request time. Task: I believed it would not scale. Action: instead of arguing, I proposed a one-day spike, measured both approaches with realistic data, and shared numbers showing the database-backed indexer answered queries 40 times faster. Result: the team chose the indexer, my teammate led its reorg handling, and we agreed to settle future debates with quick experiments.
41

How does the EIP-1559 fee model work?

Save to ▾
Show answer
EIP-1559 splits the fee into a base fee and a priority fee. The protocol sets the base fee per block from demand: if the previous block was more than half full, it rises up to 12.5 percent, otherwise it falls. The base fee is burned. Users add a priority fee (tip) for the proposer and set maxFeePerGas as their cap. They pay base fee plus tip, never more than the cap, which makes fees more predictable.
42

What happens, step by step, when you send an Ethereum transaction?

Save to ▾
Show answer
The wallet builds the transaction with nonce, to, value, data, gas limit and fee fields, signs it with the private key, and sends it to a node via eth_sendRawTransaction. The node validates and gossips it to other mempools. A block builder includes it, and the proposer publishes the block. Every node executes it in the EVM, updating state and producing a receipt with status, gas used and logs. After about two epochs the block is finalised.
43

Explain storage, memory, stack and calldata in the EVM.

Save to ▾
Show answer
Storage is persistent key-value data of 32-byte slots per contract; it is the most expensive, and writes to new slots cost about 20,000 gas. Memory is a temporary byte array cleared after each call, cheap but growing in cost quadratically. The stack holds up to 1024 words for opcode operands. Calldata is the read-only input data of the transaction, the cheapest place to read external function arguments from. Choosing the right location is a key gas optimisation.
44

What are the ABI and function selectors?

Save to ▾
Show answer
The ABI (Application Binary Interface) is the JSON description of a contract's functions, events and errors, and it defines how arguments are encoded. A function selector is the first four bytes of the Keccak-256 hash of the function signature, for example transfer(address,uint256) gives 0xa9059cbb. Calldata is the selector followed by ABI-encoded arguments in 32-byte words. Wallets, ethers.js and explorers use the ABI to encode calls and decode results and events.
45

What are events and logs in Ethereum?

Save to ▾
Show answer
Events are declared in Solidity and emitted with emit; the EVM writes them as logs in the transaction receipt. Each log has the contract address, up to three indexed topics plus the event signature hash, and non-indexed data. Logs are much cheaper than storage but contracts cannot read them. Front-ends and indexers subscribe to events to update the UI, track token transfers and build history, so emitting clear events for every state change is good practice.
46

What is the difference between CREATE and CREATE2?

Save to ▾
Show answer
CREATE computes a new contract's address from the deployer's address and nonce, so the address depends on deployment order. CREATE2 computes it from the deployer address, a chosen 32-byte salt and the hash of the init code, so the address is known before deployment and is the same wherever those inputs match. CREATE2 enables counterfactual wallets, deterministic factory deployments and same-address deployments across chains, but redeploying at the same address needs care.
47

A transaction keeps failing with an out of gas error. How do you fix it?

Save to ▾
Show answer
First see whether the gas limit was too low or the function is genuinely unbounded. Run eth_estimateGas or simulate with cast run or Tenderly to see actual gas used and where it fails. If estimation is fine, raise the limit with a buffer of 10 to 20 percent. If the function loops over a growing array, redesign it with pagination or pull-based patterns, because the block gas limit will eventually make it impossible to call.
48

You need the same contract at the same address on five chains. How do you do it?

Save to ▾
Show answer
Use CREATE2 through a deterministic deployment factory that already exists at the same address on all those chains. Keep the init code identical: same compiler version, optimiser settings, constructor arguments and metadata. Pick a salt, compute the expected address off-chain, then deploy on each chain. Foundry scripts support this by passing a salt. Avoid constructor arguments that differ per chain, or move chain-specific settings into an initialiser restricted to the deployer.
49

Your dApp needs a full history of user transactions and fast queries. Reading events from the node is too slow. What do you do?

Save to ▾
Show answer
Build or use an indexer. An indexer listens to contract events from a start block, transforms them and stores them in a database like PostgreSQL, so the front-end runs normal fast queries. Options are a subgraph on The Graph, hosted indexing services, or a custom service with ethers and a queue. It must handle reorgs by tracking block hashes, support backfilling, and expose an API. Design events up front with indexed fields that queries need.
50

How do you read a contract's storage slot directly with Foundry's cast?

Save to ▾
Show answer
Use cast storage with the contract address and slot number. For mappings, compute the slot as keccak256(key . slot). # Read slot 0 (often the first state variable) cast storage 0xContractAddress 0 --rpc-url $RPC_URL # balanceOf mapping stored at slot 2, key = user address cast index address 0xUserAddress 2 cast storage 0xContractAddress <slot-from-above> --rpc-url $RPC_URL This shows that private variables are not secret: anyone can read storage.
51

How do you compute a function selector and decode calldata with cast?

Save to ▾
Show answer
cast handles ABI work from the command line. # Function selector cast sig 'transfer(address,uint256)' # 0xa9059cbb # Encode calldata cast calldata 'transfer(address,uint256)' 0xAbc... 1000000 # Decode calldata from a transaction cast 4byte-decode 0xa9059cbb000000... # Decode with a known signature cast decode-calldata 'transfer(address,uint256)' 0xa9059cbb... This is useful when checking what a wallet is really asking you to sign.
52

How are mappings stored, and why can you not iterate over them?

Save to ▾
Show answer
A mapping does not store keys. The value for key k in a mapping declared at slot p lives at storage slot keccak256(k . p). Every possible key implicitly exists with a default zero value, so the contract cannot know which keys were set or how many. To iterate, keep a separate array of keys or use OpenZeppelin EnumerableSet or EnumerableMap, accepting extra gas, or rebuild the list off-chain from emitted events.
53

What is the difference between require, revert, assert and custom errors?

Save to ▾
Show answer
require(condition, message) validates inputs and conditions, reverting with a message if false. revert stops execution explicitly and is often used with custom errors, such as error InsufficientBalance(uint256 need, uint256 have); revert InsufficientBalance(x, y); which are cheaper than strings and carry data. assert checks invariants that should never fail; a failure signals a bug and raises a Panic. Since Solidity 0.8.26 you can also pass custom errors to require.
54

How does inheritance work in Solidity, including virtual and override?

Save to ▾
Show answer
A contract inherits with is, for example contract Token is ERC20, Ownable. Parent functions that may be changed must be marked virtual, and the child must use override; with several parents you list them, as in override(A, B). Solidity uses C3 linearisation, so the order of the parent list matters, from most base to most derived, and super calls the next contract in that order. Constructors of parents run first in linearised order.
55

Compare interfaces, abstract contracts and libraries.

Save to ▾
Show answer
An interface only declares external functions, events and errors, with no state or implementation; it is used to call other contracts, like IERC20. An abstract contract can have state and implemented functions but leaves at least one unimplemented or is marked abstract, so it cannot be deployed alone. A library holds reusable functions without state; internal library functions are inlined, while external ones are deployed once and called via delegatecall. Libraries can attach to types with using for.
56

What is the difference between receive and fallback functions?

Save to ▾
Show answer
receive() external payable runs when a contract receives plain ETH with empty calldata, for example a transfer from a wallet. fallback() runs when calldata matches no function, or when ETH arrives with data and no receive exists; it must be payable to accept ETH. Proxies use fallback to delegatecall all unknown calls to the implementation. Keep both simple, since a reverting or gas-heavy receive can break senders that use transfer with its 2300 gas stipend.
57

How does arithmetic overflow work in Solidity 0.8, and when do you use unchecked?

Save to ▾
Show answer
Since 0.8.0, arithmetic is checked by default: overflow or underflow reverts with a Panic, so SafeMath is no longer needed. Checks cost a little gas. Wrapping code in an unchecked block disables them, which is safe when you have proven the value cannot overflow, such as a loop counter bounded by an array length, or subtracting after a require that a is at least b. Using unchecked carelessly reintroduces the old overflow bugs.
58

The business wants to change contract logic after launch. How do you plan for it?

Save to ▾
Show answer
Decide early whether upgradeability is needed, because it adds trust and storage risks. Options are a proxy (UUPS or Transparent) controlled by a multisig with a timelock, a parameter-driven design where only settings like fees change through governed setters, or a migration plan to a new immutable version. Whatever you choose, document it for users, protect upgrade rights, keep storage layout append-only, and test each upgrade on a fork before executing.
59

A function that distributes rewards loops over all users and is getting too expensive. How do you fix it?

Save to ▾
Show answer
Unbounded loops eventually exceed the block gas limit. Switch to a pull-based accounting model: maintain a global reward-per-token accumulator that grows when rewards are added, and store each user's last checkpoint. Users claim with reward equals balance times (current accumulator minus their checkpoint). This makes distribution O(1) for any number of users. Alternatively, use a Merkle distributor where rewards are computed off-chain and users claim with proofs.
60

You need to send ETH to hundreds of winners. Should you push payments or let them pull?

Save to ▾
Show answer
Prefer pull payments. If a contract pushes ETH in a loop, one recipient that reverts, perhaps a contract without receive, can block everyone, and the loop may exceed the gas limit. With pull payments, the contract records each winner's amount in a mapping and winners call withdraw, which zeroes their balance before sending. This isolates failures and limits reentrancy risk. Push only for small fixed lists using call with a checked result.
61

Write a Foundry unit test and a fuzz test for a contract.

Save to ▾
Show answer
Foundry tests are Solidity contracts; functions starting with test run as tests, and parameters make them fuzz tests. import {Test} from 'forge-std/Test.sol'; import {Vault} from '../src/Vault.sol'; contract VaultTest is Test { Vault v; function setUp() public { v = new Vault(); } function testDeposit() public { v.deposit{value: 1 ether}(); assertEq(v.balanceOf(address(this)), 1 ether); } function testFuzzDeposit(uint96 amt) public { vm.assume(amt > 0); vm.deal(address(this), amt); v.deposit{value: amt}(); assertEq(address(v).balance, amt); } } Run with forge test -vvv.
62

Write a simple escrow contract where a buyer deposits and releases payment to a seller.

Save to ▾
Show answer
pragma solidity ^0.8.24; contract Escrow { address public immutable buyer; address payable public immutable seller; bool public released; constructor(address payable _seller) payable { buyer = msg.sender; seller = _seller; } function release() external { require(msg.sender == buyer, 'only buyer'); require(!released, 'done'); released = true; (bool ok, ) = seller.call{value: address(this).balance}(''); require(ok, 'transfer failed'); } } State is updated before the external call to follow checks-effects-interactions.
63

Write a basic voting contract using a struct, mapping and event.

Save to ▾
Show answer
pragma solidity ^0.8.24; contract Voting { struct Proposal { string name; uint256 votes; } Proposal[] public proposals; mapping(address => bool) public hasVoted; event Voted(address indexed voter, uint256 indexed id); constructor(string[] memory names) { for (uint256 i; i < names.length; i++) proposals.push(Proposal(names[i], 0)); } function vote(uint256 id) external { require(!hasVoted[msg.sender], 'already voted'); hasVoted[msg.sender] = true; proposals[id].votes++; emit Voted(msg.sender, id); } } An out-of-range id reverts automatically.
64

How did you handle a time you received critical code review feedback?

Save to ▾
Show answer
Situation: a senior reviewer rejected my pull request for a staking feature, saying the storage layout would break future upgrades. Task: fix it and learn. Action: I thanked him, asked him to explain the risk, read about EIP-1967 and storage gaps, rewrote the contract with namespaced storage, and added a storage-layout check to CI. Result: the PR merged, and that check later caught a teammate's layout change before an upgrade.
65

How have you mentored junior developers on a smart contract team?

Save to ▾
Show answer
Situation: our team hired three freshers who knew Solidity syntax but not security. Task: get them productive safely. Action: I created a two-week plan with Ethernaut challenges, pair-programmed their first features, and made them write tests before code. In reviews I explained why, not just what, and kept a shared checklist of common bugs. Result: within two months they shipped features independently, and one found a rounding bug during an internal review.
66

What is a reentrancy attack?

Save to ▾
Show answer
Reentrancy happens when a contract makes an external call, such as sending ETH, before updating its own state, and the receiver calls back into the contract to repeat the action. For example, a withdraw that sends funds and then sets the balance to zero can be re-entered to withdraw many times. The 2016 DAO hack drained millions this way. Prevent it with checks-effects-interactions, reentrancy guards, and pull payments.
67

What are front-running and sandwich attacks, and how do you mitigate them?

Save to ▾
Show answer
Pending transactions are public, so bots can copy or outbid them. Front-running is placing a transaction ahead of a victim's, for example buying before a large purchase. A sandwich attack buys before the victim's swap and sells right after, profiting from the price impact. Mitigations include slippage limits and deadlines, commit-reveal schemes, batch auctions, private transaction relays, and design that does not reward ordering, such as using time-weighted prices.
68

What are common access control vulnerabilities?

Save to ▾
Show answer
Typical bugs include missing onlyOwner or role checks on sensitive functions such as mint, withdraw or setOracle, initialiser functions in upgradeable contracts that anyone can call, misconfigured roles, and a single EOA owning critical powers. Use OpenZeppelin Ownable2Step or AccessControl, give each role the minimum rights, protect admin actions with a multisig and timelock, and write tests confirming that every privileged function reverts for unauthorised callers.
69

How can a smart contract suffer denial of service?

Save to ▾
Show answer
Common causes: loops over arrays that grow with users until they exceed the block gas limit; push payments in a loop where one reverting recipient blocks everyone; relying on an external call that an attacker can make fail; and griefing by filling storage cheaply. For example, an auction that refunds the previous bidder will freeze if that bidder is a contract that reverts. Use pull payments, bounded loops, pagination and failure isolation.
70

Why is on-chain randomness insecure, and what should you use instead?

Save to ▾
Show answer
Values like block.timestamp, blockhash or block.prevrandao are visible to or partly controlled by block producers, and any contract can read them in the same transaction and only proceed when the outcome is favourable. So lotteries and NFT trait reveals based on them can be gamed. Use a verifiable random function such as Chainlink VRF, which delivers randomness with a cryptographic proof in a later transaction, or a commit-reveal scheme for simpler cases.
71

Why should you check return values of low-level calls and use SafeERC20?

Save to ▾
Show answer
Low-level call, send and delegatecall return false instead of reverting on failure, so ignoring the result means the contract continues as if the transfer succeeded. Similarly, some ERC-20 tokens do not return a bool from transfer, and others return false instead of reverting. OpenZeppelin's SafeERC20 wraps transfer, transferFrom and approve to handle both cases and revert on failure. Always write (bool ok, ) = to.call{value: x}(''); require(ok).
72

What is a signature replay attack and how do you prevent it?

Save to ▾
Show answer
If a contract accepts a signed message to perform an action, an attacker can resubmit the same signature to repeat it, or replay it on another chain or another contract using the same code. Prevent it by including a per-user nonce that increments on use, a deadline, the chain ID and the verifying contract address in the signed data. EIP-712 typed data with a domain separator gives a standard way to include these fields.
73

What does a smart contract audit process look like?

Save to ▾
Show answer
It starts with scoping: fixed commit, documentation, threat model and test coverage. Auditors run automated tools like Slither and fuzzers, then do manual line-by-line review, checking business logic, access control, economic attacks and integrations. They write findings rated critical, high, medium, low and informational with fixes. The team fixes issues, auditors review the fixes, and a final report is published. Audits reduce risk but do not guarantee safety, so add bug bounties and monitoring.
74

Which tools do you use for static analysis and fuzzing of smart contracts?

Save to ▾
Show answer
Slither performs static analysis and quickly flags reentrancy, unchecked calls, shadowing and more. Aderyn is another fast static analyser. Foundry provides fuzz and invariant testing, where random sequences of calls try to break properties you define. Echidna and Medusa are property-based fuzzers. Mythril and Halmos use symbolic execution, and Certora offers formal verification. Combining them with manual review and high test coverage catches far more than any single tool.
75

An auditor flags that a single owner key can mint tokens and change fees. How do you address it?

Save to ▾
Show answer
This is centralisation risk: if the key is compromised or misused, users lose funds. Move ownership to a multisig with signers on separate devices, add a timelock so users can see and react to changes, set hard-coded bounds such as a maximum fee, and remove powers that are not needed, like unlimited minting. Use role-based access instead of one all-powerful owner, and document the remaining admin powers publicly.
76

Your team is preparing a contract for an external audit. What do you do beforehand?

Save to ▾
Show answer
Freeze the code at a commit and stop adding features. Write clear documentation: architecture, roles, trust assumptions, invariants and known risks. Reach high test coverage including fuzz and invariant tests, and run Slither and fix its findings. Remove dead code, add NatSpec comments, and make the build reproducible. Share a scope list and a walkthrough call. A clean, well-documented codebase lets auditors spend their limited time on deep logic bugs.
77

Show a contract vulnerable to reentrancy and a fixed version.

Save to ▾
Show answer
Vulnerable: the balance is cleared after sending. function withdraw() external { uint256 bal = balances[msg.sender]; (bool ok, ) = msg.sender.call{value: bal}(''); require(ok); balances[msg.sender] = 0; } Fixed: update state first and add a guard. import {ReentrancyGuard} from '@openzeppelin/contracts/utils/ReentrancyGuard.sol'; function withdraw() external nonReentrant { uint256 bal = balances[msg.sender]; require(bal > 0, 'nothing'); balances[msg.sender] = 0; (bool ok, ) = msg.sender.call{value: bal}(''); require(ok, 'send failed'); }
78

Tell me about a bug you missed and what you learned from it.

Save to ▾
Show answer
Situation: I shipped a rewards contract where a rounding error let users claim slightly more than earned when claiming very often. Task: fix it and prevent repeats. Action: I owned the mistake in the team call, wrote a failing test reproducing it, changed the division order to round down in the protocol's favour, and added fuzz tests on claim frequency. Result: losses were tiny, and I now always fuzz any maths involving division.
79

How does a constant product automated market maker work, and what is impermanent loss?

Save to ▾
Show answer
A constant product AMM holds two tokens with reserves x and y and keeps x times y equal to k. A trader adds one token and removes the other so that k stays constant after fees, which makes price equal to the reserve ratio and rise with trade size. Liquidity providers earn fees, but when prices move, arbitrage rebalances the pool, leaving them worse off than simply holding; that gap is impermanent loss.
80

Calculate the output of a swap in a constant product pool with a 0.3 percent fee.

Save to ▾
Show answer
Formula: amountOut = (amountIn x 997 x reserveOut) / (reserveIn x 1000 + amountIn x 997). Example: reserves 1,000 ETH and 3,000,000 USDC, swap 10 ETH. amountInWithFee = 10 x 997 = 9,970 numerator = 9,970 x 3,000,000 = 29,910,000,000 denominator = 1,000 x 1000 + 9,970 = 1,009,970 amountOut = 29,615 USDC (approx) The spot price is 3,000, but the trader gets about 2,961.5 per ETH because of fee and price impact.
81

How do you calculate a borrower's health factor in a lending protocol?

Save to ▾
Show answer
Health factor = (sum of collateral value x liquidation threshold) / total debt value. Below 1, the position can be liquidated. Example: collateral 10 ETH at 3,000 dollars = 30,000 dollars, liquidation threshold 80 percent, debt 18,000 dollars of stablecoins. HF = (30,000 x 0.80) / 18,000 = 1.33. If ETH falls to 2,250, collateral is 22,500, so HF = 18,000 / 18,000 = 1.0 and liquidation begins. Users raise HF by repaying debt or adding collateral.
82

How do you read a Chainlink price feed in Solidity safely?

Save to ▾
Show answer
import {AggregatorV3Interface} from '@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol'; AggregatorV3Interface public feed; uint256 constant MAX_DELAY = 1 hours; function getPrice() public view returns (uint256) { (, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData(); require(answer > 0, 'bad price'); require(block.timestamp - updatedAt <= MAX_DELAY, 'stale price'); return uint256(answer); // scale using feed.decimals(), often 8 } Always check staleness, sign and decimals; on L2s also check the sequencer uptime feed.
83

Design token vesting for team members and early investors.

Save to ▾
Show answer
Use a vesting contract that holds allocated tokens and releases them on a schedule, typically a one-year cliff followed by monthly or linear vesting over two to four years. OpenZeppelin VestingWallet gives linear vesting per beneficiary; add a cliff and an owner-controlled revoke for employees who leave, returning unvested tokens. Make schedules public on-chain for transparency, and avoid admin functions that could release tokens early, as that erodes investor trust.
84

You are launching a 10,000-piece NFT collection and fear gas wars and bots. How do you design the mint?

Save to ▾
Show answer
Avoid a first-come public rush. Use an allowlist phase with Merkle proofs or signatures, per-wallet limits, and staggered time slots. Consider a Dutch auction or raffle so price, not gas, decides allocation. Use ERC-721A or efficient batch minting to cut gas. Reveal traits later with Chainlink VRF so bots cannot snipe rare items. Load-test the front-end and RPC, and keep pause functions ready in case something goes wrong.
85

Users complain they received far fewer tokens than expected on large swaps. What is happening and how do you help?

Save to ▾
Show answer
Large trades in shallow pools suffer price impact, and wide slippage settings let sandwich bots extract extra value. Show the expected output, price impact and minimum received before confirming. Set sensible default slippage, such as 0.5 percent for major pairs, and warn when impact is high. Use a router or aggregator that splits trades across pools, and offer private transaction submission so bots cannot see the swap in the public mempool.
86

A user lost funds on our DeFi app due to their own mistake and is angry. How would you handle it?

Save to ▾
Show answer
Situation: a user sent tokens to the contract address directly instead of using deposit, and they were stuck. Task: support him honestly. Action: I listened, explained calmly what happened without blaming him, checked whether a recovery function existed, and escalated to the team. We had a rescue function for stray tokens behind the multisig, so after verification we returned them. Result: he thanked us publicly, and we added a front-end warning.
87

Tell me about working with product, legal or compliance teams on a blockchain feature.

Save to ▾
Show answer
Situation: we planned a token reward feature for Indian users, and legal raised VDA tax and securities concerns. Task: as tech lead I had to find a compliant design. Action: I ran workshops to understand their constraints, proposed non-transferable points that convert to vouchers, and documented the data flow for compliance. Result: we launched a month later than planned but with sign-off from all teams, and avoided a costly redesign after launch.
88

How do you listen to contract events and query past events with ethers?

Save to ▾
Show answer
Use contract.on for live events and queryFilter for history. const abi = ['event Transfer(address indexed from, address indexed to, uint256 value)']; const token = new Contract(TOKEN, abi, provider); token.on('Transfer', (from, to, value, event) => { console.log(from, to, value.toString(), event.log.blockNumber); }); const filter = token.filters.Transfer(null, MY_ADDRESS); const past = await token.queryFilter(filter, -5000); // last 5000 blocks console.log(past.length); Use a WebSocket provider for live events, and page large ranges because providers limit block spans.
89

How do you read a contract and send a transaction with viem?

Save to ▾
Show answer
viem is a typed, lightweight alternative to ethers, and wagmi builds React hooks on it. import { createPublicClient, createWalletClient, http, custom } from 'viem'; import { sepolia } from 'viem/chains'; const pub = createPublicClient({ chain: sepolia, transport: http() }); const count = await pub.readContract({ address: ADDR, abi, functionName: 'count' }); const wallet = createWalletClient({ chain: sepolia, transport: custom(window.ethereum) }); const [account] = await wallet.requestAddresses(); const hash = await wallet.writeContract({ address: ADDR, abi, functionName: 'increment', account }); await pub.waitForTransactionReceipt({ hash });
90

Write a Foundry deployment script.

Save to ▾
Show answer
// script/Deploy.s.sol pragma solidity ^0.8.24; import {Script, console} from 'forge-std/Script.sol'; import {Counter} from '../src/Counter.sol'; contract Deploy is Script { function run() external returns (Counter c) { vm.startBroadcast(); c = new Counter(); vm.stopBroadcast(); console.log('Counter deployed at', address(c)); } } # Run it with an encrypted keystore account forge script script/Deploy.s.sol --rpc-url $RPC_URL \ --account deployer --broadcast --verify Broadcast output in the broadcast folder records addresses for later scripts.
91

How do you store an NFT image on IPFS and use it in your contract?

Save to ▾
Show answer
Upload the image to IPFS using a node or a pinning service, which returns a CID. Create a metadata JSON file whose image field is ipfs://<imageCID>, then upload the metadata folder to get a folder CID. Set the contract's base URI to ipfs://<folderCID>/ so tokenURI(5) resolves to the file for token 5. Pin the content with more than one provider, and use a gateway URL only for display in the front-end.
92

How do you test against real mainnet contracts using a fork?

Save to ▾
Show answer
Anvil or Foundry tests can fork a live chain at a block, so you interact with real tokens and protocols locally. # Start a local fork anvil --fork-url $MAINNET_RPC --fork-block-number 21000000 # Or fork inside a test function setUp() public { vm.createSelectFork(vm.envString('MAINNET_RPC'), 21000000); } # Give yourself tokens or impersonate a whale deal(address(usdc), alice, 1_000e6); vm.prank(whale); Pinning the block number keeps results reproducible and makes RPC caching effective.
93

How do you handle a user on the wrong network in your dApp?

Save to ▾
Show answer
Check chainId after connecting and listen for chainChanged. Then ask the wallet to switch, and add the chain if it is unknown. const target = '0xaa36a7'; // Sepolia 11155111 try { await window.ethereum.request({ method: 'wallet_switchEthereumChain', params: [{ chainId: target }] }); } catch (e) { if (e.code === 4902) { await window.ethereum.request({ method: 'wallet_addEthereumChain', params: [{ chainId: target, chainName: 'Sepolia', rpcUrls: [RPC], nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 } }] }); } } Disable write buttons until the network is correct.
94

After a transaction is confirmed, your front-end still shows old data. How do you fix it?

Save to ▾
Show answer
The UI is probably reading cached results or a lagging RPC node. After tx.wait() resolves, explicitly refetch or invalidate the relevant queries, for example with wagmi or TanStack Query invalidation. Show optimistic updates while pending. If you use an indexer, it may lag by a few blocks, so poll until it reaches the receipt's block number. Use the same RPC endpoint for writes and immediate reads, and avoid long caching for balances.
95

Your RPC provider starts rate-limiting and the dApp breaks during peak traffic. What do you do?

Save to ▾
Show answer
Short term, add a fallback transport with multiple providers so requests fail over automatically, and use retries with backoff. Reduce load: batch calls with multicall, cache read results, use WebSockets instead of tight polling, and move history queries to an indexer. Long term, upgrade the plan, spread traffic across providers or run your own node for critical paths, and monitor error rates and latency with alerts so you learn of issues before users do.
96

Your fantasy sports contract needs live match scores. How do you get that data on-chain?

Save to ▾
Show answer
Smart contracts cannot call web APIs, so use an oracle. Options include a decentralised oracle network such as Chainlink Functions to fetch from several sports APIs and aggregate, or an optimistic oracle where results are proposed and can be disputed. Settle only after the match result is final, use multiple data sources, add a dispute window for high-value pools, and handle cancelled matches. Avoid a single back-end key posting results, which is a central point of failure.
97

Your target users in India have never used crypto wallets. How do you design onboarding?

Save to ▾
Show answer
Hide crypto complexity. Offer login with phone or email using embedded or smart contract wallets, so no seed phrase is needed at first. Sponsor gas with a paymaster so users need no tokens. Show amounts in rupees and plain language, support regional languages, and explain actions in simple terms. Provide account recovery via passkeys or guardians, and let advanced users export to self-custody later. Ensure KYC and tax requirements are clear where money is involved.
98

How do you handle unclear or changing requirements from a client?

Save to ▾
Show answer
Situation: a client asked for a marketplace dApp but kept changing royalty and fee rules. Task: deliver without endless rework. Action: I wrote a short spec with examples and edge cases, got sign-off, and made fees configurable parameters with limits instead of hard-coded logic. Changes went through a simple change log with impact estimates. Result: we delivered in eight weeks, and later fee changes needed only a governance transaction, not a redeployment.

Frequently asked questions

Who should practise medium Blockchain questions?

Anyone with some hands-on practice: most real interview time is spent on medium questions like these.

How should I practise these?

Answer each question aloud before opening the answer, mark it as solved only when your answer matches the key idea, and save misses to Last-Minute Revision.

Other difficulty levels