By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
Study Guide – What is Blockchain (Distributed Ledger, Immutability, Consensus)
A blockchain is a distributed ledger that lives on many computers at once, where every new block of transactions is cryptographically linked to the previous one. Because the data is replicated, signed, and never overwritten, the system is immutable and its state is decided by a consensus algorithm rather than a single authority. In practice this lets anyone build trust‑less apps—e.g., a Uniswap swap that settles instantly without a central exchange, an NFT minting contract that guarantees provenance, or a DAO voting contract that records every vote on‑chain and can’t be tampered with.
parentHash
timestamp
nonce
stateRoot
bytes32 public parentHash;
bytes32 public merkleRoot;
Solidity snippet – a minimal immutable record contract
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; contract ImmutableLog { event Log(address indexed sender, string data, uint256 timestamp); // Anyone can write, but nothing can be deleted or altered function write(string calldata _data) external { emit Log(msg.sender, _data, block.timestamp); } }
Block Header Fields (EIP‑1559 example) solidity struct Header { bytes32 parentHash; bytes32 stateRoot; bytes32 receiptsRoot; uint256 blockNumber; uint256 gasUsed; uint256 baseFeePerGas; // new after London fork }
solidity struct Header { bytes32 parentHash; bytes32 stateRoot; bytes32 receiptsRoot; uint256 blockNumber; uint256 gasUsed; uint256 baseFeePerGas; // new after London fork }
Consensus Example – PoS validator set (pseudo‑JS) js const ethers = require('ethers'); const provider = new ethers.InfuraProvider('goerli', INFURA_KEY); const validator = new ethers.Wallet(PRIVATE_KEY, provider); // validator signs the block proposal const signature = await validator.signMessage(blockHash);
js const ethers = require('ethers'); const provider = new ethers.InfuraProvider('goerli', INFURA_KEY); const validator = new ethers.Wallet(PRIVATE_KEY, provider); // validator signs the block proposal const signature = await validator.signMessage(blockHash);
Merkle Proof Verification (Solidity) solidity function verifyProof(bytes32 leaf, bytes32[] calldata proof, bytes32 root) external pure returns (bool) { bytes32 computed = leaf; for (uint i = 0; i < proof.length; i++) { computed = keccak256(abi.encodePacked(computed < proof[i], computed, proof[i])); } return computed == root; }
solidity function verifyProof(bytes32 leaf, bytes32[] calldata proof, bytes32 root) external pure returns (bool) { bytes32 computed = leaf; for (uint i = 0; i < proof.length; i++) { computed = keccak256(abi.encodePacked(computed < proof[i], computed, proof[i])); } return computed == root; }
Finality Gadget (Ethereum’s Casper FFG) Validators submit attestations; when >2/3 of total stake have attested, the block is finalized and cannot be reverted without slashing.
ImmutableLog
npx hardhat compile
js const ethers = require('ethers'); const provider = new ethers.InfuraProvider('goerli', INFURA_KEY); const wallet = new ethers.Wallet(PRIVATE_KEY, provider); const factory = new ethers.ContractFactory(abi, bytecode, wallet); const contract = await factory.deploy(); // tx sent await contract.deployed(); // wait for receipt console.log('Deployed at', contract.address);
write("first entry")
js const tx = await contract.write("first entry"); await tx.wait(); // block mined, immutable log entry created
verifyProof
Mistake: Using tx.origin for access control. Correction: Use msg.sender (or role‑based AccessControl) because tx.origin can be spoofed through a malicious contract call chain.
tx.origin
msg.sender
AccessControl
Mistake: Assuming a block is final after 1 confirmation. Correction: Wait for the network’s finality threshold (e.g., 6 confirmations on Ethereum PoW, or a finalized checkpoint on PoS) to avoid reorg attacks.
Mistake: Hard‑coding gas limits (gas: 21000) for contract calls. Correction: Let the node estimate gas (estimateGas) or use gasLimit: ethers.constants.MaxUint256 and let the EVM cap it; over‑estimation wastes ETH, under‑estimation causes OOG failures.
gas: 21000
estimateGas
gasLimit: ethers.constants.MaxUint256
Mistake: Storing large data (e.g., images) directly in contract storage. Correction: Store a hash/IPFS CID on‑chain and keep the heavy payload off‑chain; this preserves immutability while keeping gas low.
Mistake: Forgetting to enable the Solidity optimizer. Correction: In hardhat.config.js, set optimizer: { enabled: true, runs: 200 }; otherwise you’ll pay unnecessary gas for every operation.
hardhat.config.js
optimizer: { enabled: true, runs: 200 }
Call vs. delegatecall: Interviewers love to ask why delegatecall is dangerous. delegatecall runs the callee’s code in the caller’s context, so a malicious library can overwrite the caller’s storage. Expect to discuss the “proxy pattern” and why you must whitelist the implementation address.
delegatecall
ERC‑20 vs. ERC‑777: Be ready to compare the basic token interface (transfer/approve) with ERC‑777’s hooks (tokensReceived) and operator model, which mitigates the “approval race” problem.
tokensReceived
Optimistic vs. ZK Rollups: Explain that Optimistic Rollups assume transactions are valid and use fraud proofs (challenge window), while ZK Rollups generate succinct validity proofs on‑chain, offering instant finality but higher proving costs.
Gas‑price vs. Base‑fee: Show you understand EIP‑1559: maxFeePerGas = baseFee + maxPriorityFee. Auditors will check that your dApp correctly caps maxFeePerGas to avoid over‑paying during spikes.
maxFeePerGas = baseFee + maxPriorityFee
maxFeePerGas
Scenario: A contract uses tx.origin to restrict withdrawals to the original sender. Answer: It’s unsafe because a malicious contract can trick a user into calling it, making tx.origin point to the user while the malicious contract executes the withdrawal.
Scenario: After a hard fork, a block that was previously final becomes “orphaned”. What went wrong? Answer: The network’s consensus changed; you should rely on the finalized checkpoint (e.g., Casper FFG) rather than a simple confirmation count, because forks can reorganize non‑finalized blocks.
Scenario: You see a contract that stores a 1 MB PNG in a bytes state variable. Answer: This is a gas‑inefficient anti‑pattern; store the file off‑chain (IPFS/S3) and keep only its hash or CID on‑chain.
bytes
baseFee
maxPriorityFee
runs: 200
uint256 private _status; modifier nonReentrant() { require(_status == 1); _status = 2; _; _status = 1; }
pragma solidity ^0.8.24;
bytes32 constant IMPLEMENTATION_SLOT = keccak256("my.proxy.implementation")
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.