Skip to content
RED SAGSkills

Blockchain interview questions and answers

Blockchain interview questions cover how chains reach agreement, how smart contracts run and the bugs that cost real money.

Below are 60 Blockchain questions with the correct answer and a short explanation, grouped from fresher to experienced level. Try each one before you open the answer.

What Blockchain interviews usually check

  • ✓Blocks, hashing and consensus
  • ✓Transactions, gas and the EVM
  • ✓Solidity basics
  • ✓Smart contract vulnerabilities
  • ✓Tokens, wallets and DeFi basics

Blockchain interview questions for freshers easy

1. Changing deployed code

You deployed a normal (non-proxy) smart contract and found a bug. Can you edit its code at the same address?

  1. A.Yes, call the update() function every contract has
  2. B.Yes, Etherscan lets you edit verified code
  3. C.No, deployed bytecode cannot be changed; you must deploy a new contract (or use an upgrade pattern designed in advance)
  4. D.Yes, but only within 24 hours
Show answer

Answer: C. No, deployed bytecode cannot be changed; you must deploy a new contract (or use an upgrade pattern designed in advance)

Contract bytecode is stored permanently on chain. Upgrades are only possible if you planned for them, for example with a proxy that points to a new implementation. This is why testing and audits matter so much.

2. Why emit events

Why do smart contracts emit events, such as Transfer(from, to, amount)?

  1. A.To let off-chain apps and indexers track activity cheaply through transaction logs
  2. B.To store data that other contracts can read later
  3. C.To make the transaction run faster
  4. D.To encrypt the transaction
Show answer

Answer: A. To let off-chain apps and indexers track activity cheaply through transaction logs

Events are written to transaction logs, which are much cheaper than storage. Frontends, indexers like The Graph and explorers listen to them. Contracts cannot read logs, so on-chain logic must use storage instead.

3. The account nonce

What is the nonce of an Ethereum externally owned account (EOA) used for?

  1. A.It counts the transactions sent from the account, so each one is ordered and cannot be replayed
  2. B.It is the secret number used to derive the private key
  3. C.It is the reward a validator gets for a block
  4. D.It sets the maximum gas the account may spend per day
Show answer

Answer: A. It counts the transactions sent from the account, so each one is ordered and cannot be replayed

Each transaction from an EOA carries a nonce equal to the number of transactions already sent. Nodes only accept the next nonce in order, which stops the same signed transaction from being included twice. It also lets you replace a stuck transaction by sending a new one with the same nonce and a higher fee.

4. Wei and ether

How many wei are in 1 ether?

  1. A.10^9
  2. B.10^18
  3. C.10^6
  4. D.10^12
Show answer

Answer: B. 10^18

1 ether equals 10^18 wei, and wei is the smallest unit that contracts work with. Gwei (10^9 wei) is commonly used for gas prices. In Solidity you can write 1 ether or 1 gwei as literals to avoid counting zeros.

5. Sending ETH to a function

A user calls deposit() and sends 1 ETH with the call, but the transaction reverts. The function is declared function deposit() external { ... }. What is the most likely cause?

  1. A.Functions cannot receive ETH; only the constructor can
  2. B.The user must first approve the contract to take their ETH
  3. C.The function is missing the payable keyword, so it rejects any call with ETH attached
  4. D.ETH can only be sent to contracts through a token bridge
Show answer

Answer: C. The function is missing the payable keyword, so it rejects any call with ETH attached

In Solidity, a function only accepts ETH if it is marked payable. A non-payable function reverts if msg.value is greater than zero. ETH is native, so it never needs an ERC-20 style approval.

6. Reading a missing mapping key

What does this function return for an address that was never added?

mapping(address => uint256) public balances;

function balanceOf(address user) external view returns (uint256) {
    return balances[user];
}
  1. A.It reverts with "key not found"
  2. B.It returns the maximum uint256 value
  3. C.It returns the last value written to the mapping
  4. D.It returns 0, because every possible key already maps to the default value
Show answer

Answer: D. It returns 0, because every possible key already maps to the default value

Solidity mappings have no notion of a missing key: every key maps to the zero value of its type until written. So an unknown address returns 0. If you need to know whether a key was ever set, keep a separate flag or use a value that cannot be zero.

7. What revert undoes

A function updates two storage variables and then hits a require that fails. What happens?

  1. A.The first two updates are kept, and only later code is skipped
  2. B.The transaction is retried automatically in the next block
  3. C.All state changes made in the call are rolled back, but the sender still pays for the gas used
  4. D.All changes are rolled back and the sender gets the full fee refunded
Show answer

Answer: C. All state changes made in the call are rolled back, but the sender still pays for the gas used

A revert undoes every state change made during the call, so the contract is left as it was. However, the validator still did the work, so the sender pays for the gas used up to the revert. That is why failing early with checks at the top of a function is cheaper.

8. When a block is final

On Ethereum proof of stake, roughly when does a block become finalized, meaning it cannot be reverted without validators losing a large amount of stake?

  1. A.Instantly, as soon as it is proposed
  2. B.After 1 hour
  3. C.After 7 days
  4. D.After about two epochs, roughly 13 minutes
Show answer

Answer: D. After about two epochs, roughly 13 minutes

Ethereum has 12-second slots and 32-slot epochs. A block is usually finalized once the epoch containing it is justified and the next one confirms it, which takes about two epochs or roughly 13 minutes. Before that, short reorgs are possible, so exchanges and bridges often wait for finality.

9. Running out of gas

A transaction is sent with a gas limit that turns out to be too low and it runs out of gas halfway. What is the result?

  1. A.The completed steps are saved and the rest is skipped
  2. B.The transaction fails, all its state changes are reverted, and the gas used is still paid
  3. C.The network adds extra gas automatically and charges later
  4. D.The transaction waits in the mempool until more gas is sent
Show answer

Answer: B. The transaction fails, all its state changes are reverted, and the gas used is still paid

Running out of gas is an exceptional halt, so all state changes are reverted. Validators still did the work, so the fee for the gas consumed is charged. Wallets estimate gas with a simulation and add a margin to avoid this.

10. A 2-of-3 multisig wallet

A startup's treasury uses a 2-of-3 multisig such as Safe, with keys held by the CEO, CFO and CTO. What does this mean?

  1. A.All three must sign every transaction
  2. B.Each person can move up to two-thirds of the funds alone
  3. C.Any two of the three must sign before funds can move
  4. D.Two people hold the keys and one is a backup email
Show answer

Answer: C. Any two of the three must sign before funds can move

An m-of-n multisig needs m signatures from n owners. Here losing one key does not lock the funds, and one stolen key cannot drain them. Signers should use separate devices and check each transaction before signing.

11. Bitcoin's UTXO model

Alice has one Bitcoin output worth 0.5 BTC and pays Bob 0.2 BTC. What does her transaction usually create?

  1. A.A balance update from 0.5 to 0.3 in Alice's account
  2. B.An output of 0.2 BTC to Bob and a change output back to Alice
  3. C.One 0.5 BTC output to Bob, who refunds the rest
  4. D.A request that Bob's wallet must approve first
Show answer

Answer: B. An output of 0.2 BTC to Bob and a change output back to Alice

Bitcoin tracks unspent transaction outputs, not account balances. A transaction spends whole outputs and creates new ones, so Alice sends 0.2 to Bob and the rest, minus the fee, back to a change address she controls.

12. Anyone can mint

What is the security problem in this token?

function mint(address to, uint256 amount) external {
    _mint(to, amount);
}
  1. A._mint cannot be called from an external function
  2. B.There is no access control, so anyone can mint
  3. C.The amount should be checked for overflow by hand
  4. D.Minting to the zero address is always allowed
Show answer

Answer: B. There is no access control, so anyone can mint

Without onlyOwner, onlyRole(MINTER_ROLE) or a similar check, any address can create unlimited tokens and crash the price. Missing access control on sensitive functions is one of the most common and costly bugs. Review every external and public function for who should be allowed to call it.

13. Protecting the admin key

A protocol's owner role is a single developer's hot wallet that can upgrade contracts holding millions. What is the standard improvement?

  1. A.Back up the private key in a cloud drive
  2. B.Share the key with two other developers
  3. C.Rotate the key to a new hot wallet monthly
  4. D.Move ownership to a multisig such as a Safe
Show answer

Answer: D. Move ownership to a multisig such as a Safe

A multisig needs several independent signers (for example 3 of 5), so one stolen or compromised key cannot act alone. Sharing one key spreads risk rather than reducing it. Combine a multisig with a timelock for upgrades and hardware wallets for signers.

14. Why add a timelock

Governance actions such as upgrades must wait 48 hours in a timelock before they execute. What does that give users?

  1. A.Faster upgrades with fewer signatures
  2. B.Protection against all smart contract bugs
  3. C.Time to review the change and exit if they disagree
  4. D.Lower gas costs for the upgrade transaction
Show answer

Answer: C. Time to review the change and exit if they disagree

A timelock queues admin actions publicly for a fixed delay, so users and watchers can inspect them and withdraw before a malicious or risky change takes effect. It does not stop bugs in the code itself. Emergency pause roles are often kept separate so urgent fixes are still possible.

15. Protecting a deployer key

Which setup best protects a key that owns production contracts?

  1. A.A hot wallet browser extension on a work laptop
  2. B.A hardware wallet, ideally as one signer in a multisig
  3. C.A plain text file in an encrypted laptop folder
  4. D.A password manager note synced to the cloud
Show answer

Answer: B. A hardware wallet, ideally as one signer in a multisig

Hardware wallets keep the private key on a dedicated device and sign without exposing it to the computer. Making that device one signer of a multisig removes the single point of failure. Software wallets and files are exposed to malware on the host.

16. 100% test coverage

A team reports 100% line coverage for its contracts. What does that tell you about security?

  1. A.The contracts have no exploitable bugs left in them
  2. B.An external audit is no longer needed before launch
  3. C.Every possible input value was tested at least once
  4. D.Every line ran in tests, not that attacks were tested
Show answer

Answer: D. Every line ran in tests, not that attacks were tested

Coverage shows that lines executed, not that the tests asserted the right things or tried hostile sequences. Most exploits come from unexpected combinations and economics. Add fuzzing, invariant tests, adversarial scenarios and reviews.

17. Red flags in a new token

A new token's verified code lets the owner mint any amount at any time and change transfer fees up to 100%. What does that mean for buyers?

  1. A.Holders are protected by the token standard
  2. B.The owner can dilute holders or block sales at will
  3. C.Those functions are disabled once trading starts
  4. D.Only the blockchain validators can use them
Show answer

Answer: B. The owner can dilute holders or block sales at will

Unlimited minting and adjustable fees are centralisation risks: the owner can print tokens and dump them, or set sell fees so holders cannot exit. Look for capped supply, renounced or timelocked admin roles, and fee limits in code before trusting a token.

18. Calculating a transaction fee

A transaction uses 50,000 gas and the effective gas price is 20 gwei. What is the fee?

  1. A.0.01 ETH
  2. B.0.001 ETH
  3. C.0.0001 ETH
  4. D.1 ETH
Show answer

Answer: B. 0.001 ETH

Fee = gas used x gas price = 50,000 x 20 gwei = 1,000,000 gwei. Since 1 ETH is 10^9 gwei, that is 0.001 ETH. Under EIP-1559 the effective price is the base fee plus the priority fee actually paid.

19. Seeing why a Foundry test failed

A Foundry test fails and you want to see the full call trace, including nested calls and reverts. What helps?

  1. A.Run forge build with --sizes
  2. B.Run forge fmt before testing
  3. C.Run forge test with --gas-report only
  4. D.Run forge test with -vvvv
Show answer

Answer: D. Run forge test with -vvvv

More v flags increase verbosity: -vvv shows traces for failing tests and -vvvv shows traces for all tests, including setup. Traces show each call, its arguments, return values and where a revert happened. --gas-report summarises gas per function.

20. Authentication or authorization?

A finance clerk in Dubai logs in with her password and an Authenticator push, then gets an 'Access denied' message when opening the payroll share. Which step failed?

  1. A.Authorization: she proved who she is but lacks permission
  2. B.Authentication: her password or MFA was not accepted
  3. C.Accounting: her actions were not logged correctly
  4. D.Federation: her identity was not trusted by the file server
Show answer

Answer: A. Authorization: she proved who she is but lacks permission

Authentication proves who you are; authorization decides what you may do once you are known. She signed in successfully, so authentication worked. The 'Access denied' comes from the share's permissions, which is an authorization decision.

Blockchain intermediate interview questions medium

21. Front-running a swap

A user sends a large DEX swap with 5% slippage allowed. What can a bot watching the public mempool do?

  1. A.Nothing; transactions are private until mined
  2. B.Cancel the user's transaction
  3. C.Sandwich it: buy before the user to push the price up, then sell right after, profiting up to the slippage limit
  4. D.Change the token the user receives
Show answer

Answer: C. Sandwich it: buy before the user to push the price up, then sell right after, profiting up to the slippage limit

Pending transactions are visible, and block builders and bots can order transactions for profit (MEV). Tight slippage limits, private transaction relays and batch-auction designs reduce sandwich risk.

22. Testing against real protocols

Your contract swaps on Uniswap and deposits into Aave. What is the best way to test the integration realistically before deploying?

  1. A.Write mocks of Uniswap and Aave that return fixed values
  2. B.Run fork tests that copy mainnet state at a pinned block, then call the real deployed contracts
  3. C.Deploy straight to mainnet with a small amount
  4. D.Test only on a testnet, since mainnet state cannot be used locally
Show answer

Answer: B. Run fork tests that copy mainnet state at a pinned block, then call the real deployed contracts

Foundry and Hardhat can fork a live chain through an RPC URL and run tests against the real contracts and balances. Pinning a block number makes results repeatable and allows RPC caching. Mocks are still useful for unit tests, but they hide real behaviour like fees, rounding and token quirks.

23. Transient storage locks

Why is a reentrancy lock built on transient storage (EIP-1153, TSTORE/TLOAD) cheaper than one in normal storage?

  1. A.Transient storage is kept in the contract bytecode
  2. B.Transient values are cleared at the end of the transaction, so they cost about as little as warm storage and never pay full storage write prices
  3. C.Transient storage is free because validators do not charge for it
  4. D.Transient storage lasts until the next block, so the lock is shared by many users
Show answer

Answer: B. Transient values are cleared at the end of the transaction, so they cost about as little as warm storage and never pay full storage write prices

Since the Dencun upgrade, TSTORE and TLOAD cost about 100 gas each and the data is discarded when the transaction ends. A lock only needs to exist during one transaction, so this fits perfectly. OpenZeppelin provides ReentrancyGuardTransient, and you need a chain and compiler EVM version that support Cancun opcodes.

24. Constructors behind a proxy

Why do upgradeable contracts use an initialize() function instead of setting state in the constructor?

  1. A.Constructors are not allowed in Solidity 0.8
  2. B.The constructor runs in the implementation's own context at deployment, so its storage writes never reach the proxy's storage
  3. C.Constructors cost more gas than normal functions
  4. D.Proxies call the constructor again on every upgrade
Show answer

Answer: B. The constructor runs in the implementation's own context at deployment, so its storage writes never reach the proxy's storage

A proxy uses delegatecall, so state lives in the proxy. The implementation's constructor only writes to the implementation's storage, which the proxy never reads. So setup goes into an initializer called once through the proxy, protected by the initializer modifier, and the implementation's constructor should call _disableInitializers().

25. Later transactions all stuck

A backend hot wallet sent transactions with nonces 41, 42 and 43, but nonce 41 was dropped from the mempool. What happens to 42 and 43?

  1. A.They wait, since none can be mined before nonce 41
  2. B.They are mined right away and nonce 41 is skipped
  3. C.They are mined in reverse order, 43 first
  4. D.They fail with an "out of gas" error
Show answer

Answer: A. They wait, since none can be mined before nonce 41

Ethereum requires each account's transactions to run in strict nonce order. A missing nonce blocks every later one. The fix is to resend a transaction with nonce 41; a nonce manager in the backend should track and rebroadcast gaps.

26. Fee earned on a swap

A user swaps 1,000 USDC in a Uniswap v2 pool with a 0.3% fee. How much goes to liquidity providers as fees?

  1. A.0.3 USDC
  2. B.30 USDC
  3. C.3 USDC
  4. D.0.03 USDC
Show answer

Answer: C. 3 USDC

0.3% of 1,000 is 3. In Uniswap v2 the fee is added to the pool reserves (unless the protocol fee switch is on), which raises the value of each LP token.

27. "Cannot estimate gas" before sending

A wallet shows "cannot estimate gas, transaction may fail" before the user signs. What does this usually mean?

  1. A.A simulation reverted, so it would fail on chain
  2. B.The gas price is too high for the wallet to show
  3. C.The user has too many pending transactions
  4. D.The RPC provider does not support the chain
Show answer

Answer: A. A simulation reverted, so it would fail on chain

eth_estimateGas runs the transaction against current state. If it reverts, for example because of a missing approval, low balance or a failed require, the wallet cannot find a working gas limit. Decoding the revert reason in the frontend gives the user a clear message.

28. Effective gas price with a fee cap

A transaction sets maxFeePerGas = 40 gwei and maxPriorityFeePerGas = 15 gwei. The block's base fee is 30 gwei. What price per gas does it pay, and what tip does the validator get?

  1. A.40 gwei paid, 10 gwei tip
  2. B.45 gwei paid, 15 gwei tip
  3. C.30 gwei paid, 0 gwei tip
  4. D.40 gwei paid, 15 gwei tip
Show answer

Answer: A. 40 gwei paid, 10 gwei tip

The effective price is min(maxFee, baseFee + priorityFee) = min(40, 45) = 40 gwei. The base fee of 30 is burned, so the tip is 40 − 30 = 10 gwei. The cap protects the user when base fees rise.

29. Blind signing on a hardware wallet

A treasury signer uses a hardware wallet, but it only shows a hash for a complex Safe transaction. Why is this risky?

  1. A.The signer cannot see what they are really approving
  2. B.Hardware wallets leak the key when signing hashes
  3. C.The hash shown will be different on each signer's device
  4. D.Safe transactions cannot be signed on hardware wallets
Show answer

Answer: A. The signer cannot see what they are really approving

A hardware wallet protects the key, but if the screen only shows an opaque hash, a hacked frontend can swap in a malicious transaction. The 2025 Bybit theft worked this way. Decoding and checking the call data with an independent tool before signing reduces the risk.

30. A signed voucher used twice

A contract lets users redeem a signed voucher (recipient, amount). It checks the signature but stores nothing after use. What can a user do?

  1. A.Nothing, since a signature can only be checked once
  2. B.Change the amount without breaking the signature
  3. C.Redeem only after the signer approves again
  4. D.Submit the same signature again to redeem it many times
Show answer

Answer: D. Submit the same signature again to redeem it many times

A valid signature stays valid forever unless the contract tracks its use. Include a nonce (or a unique ID) in the signed data and mark it used, and add a deadline and the EIP-712 domain to stop replays across time, contracts and chains.

31. Lowering an allowance Bob can see

Alice approved Bob for 100 tokens and now sends approve(bob, 50). Bob sees it pending. What can he do?

  1. A.Nothing, the new approval replaces the old one at once
  2. B.Cancel Alice's transaction from the mempool
  3. C.Spend the 100 first, then also spend the new 50
  4. D.Only spend the 50 once Alice's transaction lands
Show answer

Answer: C. Spend the 100 first, then also spend the new 50

Bob can front-run with transferFrom for 100, and after Alice's approve lands, spend 50 more, for 150 in total. Mitigations are setting the allowance to 0 first, using increase/decrease helpers where available, or using permit with exact amounts.

32. Casting uint256 to uint96

A staking contract stores amounts as uint96 to pack storage and writes stake = uint96(amount). What happens if amount exceeds type(uint96).max?

  1. A.Solidity 0.8 reverts on the cast automatically
  2. B.The value is rounded to the maximum uint96
  3. C.The value is silently truncated to its low 96 bits
  4. D.The compiler refuses to build the contract
Show answer

Answer: C. The value is silently truncated to its low 96 bits

Explicit narrowing casts do not check for overflow, even in 0.8; they keep only the low bits. A huge deposit could be recorded as a tiny one, or vice versa. Use OpenZeppelin's SafeCast (toUint96) which reverts if the value does not fit.

33. Hiding a 4-digit code with a hash

A contract stores keccak256 of a 4-digit unlock code and lets anyone who submits the matching code claim a prize. Is the code safe?

  1. A.No: all 10,000 codes can be hashed off-chain in seconds
  2. B.Yes: keccak256 cannot be reversed by anyone
  3. C.Yes: storage marked private hides the hash
  4. D.No: but only miners can see the hash
Show answer

Answer: A. No: all 10,000 codes can be hashed off-chain in seconds

Hashing does not protect a small input space. Anyone can read the stored hash and try all 10,000 codes off-chain almost instantly. Also, the code is visible in the mempool when someone claims, so it can be front-run. Use signatures or commit-reveal with secret salts instead.

34. A signature that leaves out a field

A backend signs (amount, nonce) for withdrawals, and the contract pays msg.sender. The signature is sent to the user's browser. What is the risk?

  1. A.Anyone who sees the signature can claim it for themselves
  2. B.The amount can be increased by the user
  3. C.The nonce will be reused on every withdrawal
  4. D.The backend key becomes public on chain
Show answer

Answer: A. Anyone who sees the signature can claim it for themselves

The signed data does not bind the payout to a specific address, so whoever submits it first gets the funds, including a mempool bot that copies it. Sign every field that matters: recipient, amount, nonce, deadline, and the EIP-712 domain.

35. Anyone can grow a list

Anyone can add a deposit of any size to a public array that a weekly payout loops over. An attacker adds 50,000 deposits of 1 wei. What happens?

  1. A.The payout runs out of gas and can never complete
  2. B.The deposits are refunded automatically
  3. C.The loop skips entries below one token
  4. D.The attacker pays rewards to every user
Show answer

Answer: A. The payout runs out of gas and can never complete

When users can grow an array that a single transaction must loop through, an attacker can make it too large for the block gas limit, blocking the payout forever. Use minimum sizes, per-user mappings and pull-based claims, or process in bounded batches.

36. A signed order with no expiry

A marketplace accepts signed sell orders with a price and nonce but no deadline. A seller signs at 1 ETH and forgets. Months later the NFT is worth 20 ETH. What can happen?

  1. A.Anyone can still fill the old order at 1 ETH
  2. B.The order expires when the price changes
  3. C.Nonces stop the order from being used later
  4. D.The seller must sign again before any sale
Show answer

Answer: A. Anyone can still fill the old order at 1 ETH

Without an expiry, the signature stays valid until the nonce is used or cancelled. Include a deadline in signed data, check block.timestamp <= deadline, and give users an easy cancel (incrementing a nonce or marking the order cancelled).

37. A token you can buy but not sell

Users can buy a new token on a DEX, but every sell reverts. The code has a transfer hook. What is likely going on?

  1. A.The DEX does not support selling tokens in their first week
  2. B.The hook only lets allowed addresses transfer to the pool
  3. C.Users need to approve the token twice before selling
  4. D.The token has too many decimals for the DEX to sell
Show answer

Answer: B. The hook only lets allowed addresses transfer to the pool

Honeypot tokens add logic in _update or transfer that reverts or takes a 100% fee when non-whitelisted addresses send to the pair, so only the deployer can sell. Read the transfer logic and simulate a sell before buying unfamiliar tokens.

38. A burn function with a from parameter

A token adds function burn(address from, uint256 amount) external { _burn(from, amount); }. What is wrong?

  1. A.It burns the caller's tokens twice
  2. B.Burning can only be done by the owner
  3. C.Anyone can burn anyone else's tokens
  4. D._burn needs msg.value to work
Show answer

Answer: C. Anyone can burn anyone else's tokens

There is no check that the caller owns the tokens or has an allowance from from, so anyone can destroy other users' balances. Use burn(amount) for the caller, and burnFrom(from, amount) that spends allowance first, as in OpenZeppelin's ERC20Burnable.

39. Reading the same slot twice

Under EIP-2929, a function reads the same storage slot twice in one transaction. Roughly what gas do the two SLOADs cost?

  1. A.About 800 for each read
  2. B.About 2,100 for the first, 100 for the second
  3. C.About 20,000 for the first, 0 for the second
  4. D.About 100 for each read
Show answer

Answer: B. About 2,100 for the first, 100 for the second

The first access to a slot in a transaction is cold and costs 2,100 gas; later accesses are warm and cost 100. Caching a storage value in a local variable still saves the warm read and keeps code clearer. Access lists can pre-warm slots in some cases.

40. Catching gas regressions

A team wants CI to fail when a change makes key functions more expensive. Which Foundry feature supports this?

  1. A.forge snapshot with a committed .gas-snapshot file
  2. B.forge fmt --check on every pull request
  3. C.forge create to redeploy on each change
  4. D.forge coverage to track line coverage
Show answer

Answer: A. forge snapshot with a committed .gas-snapshot file

forge snapshot records gas used by each test into .gas-snapshot. Running forge snapshot --check (or --diff) in CI compares against the committed file and shows or fails on changes. Coverage and formatting do not measure gas.

Blockchain interview questions for experienced candidates hard

41. First depositor in a vault

In a new ERC-4626 vault, an attacker deposits 1 wei, then donates a large amount of assets directly to the vault before a victim deposits. What happens and how is it prevented?

  1. A.The victim's shares round down to zero or very few, and the attacker captures their deposit; prevent with virtual shares/decimals offset or a seed deposit
  2. B.Nothing happens, because donations are rejected by ERC-20 tokens
  3. C.The vault becomes paused automatically
  4. D.The attacker loses the donation and the victim gains it
Show answer

Answer: A. The victim's shares round down to zero or very few, and the attacker captures their deposit; prevent with virtual shares/decimals offset or a seed deposit

Shares are computed as assets * totalSupply / totalAssets. The donation inflates totalAssets so the victim's share count rounds down. OpenZeppelin's ERC4626 uses virtual shares and a decimals offset; protocols also seed the vault with an initial deposit.

42. Paying everyone in a loop

A contract pays rewards by looping over an array of all users and sending ETH to each in one transaction. As users grow, what breaks and what is the better design?

  1. A.Nothing breaks, because the EVM has no gas limit
  2. B.Only the first user is paid
  3. C.The loop eventually exceeds the block gas limit, and one reverting receiver can block everyone; use a pull pattern where each user claims their own reward
  4. D.Loops are not allowed in Solidity
Show answer

Answer: C. The loop eventually exceeds the block gas limit, and one reverting receiver can block everyone; use a pull pattern where each user claims their own reward

Unbounded loops grow gas use until the function cannot run, and a single contract that rejects ETH can make the whole payout revert. Pull-over-push lets users withdraw individually, and Merkle-based claims scale to millions of users.

43. Reentrancy through safeMint

A mint function limits each address to 1 NFT. An attacker's contract ends up with 20. How?

function mint() external {
    require(minted[msg.sender] == 0, "already minted");
    _safeMint(msg.sender, nextId++);
    minted[msg.sender] = 1;
}
  1. A.nextId++ overflows and resets the counter
  2. B._safeMint calls onERC721Received on the receiver before minted is set, so the attacker re-enters mint() from that callback
  3. C._safeMint is not allowed for contracts, so the check is skipped
  4. D.require does not work inside external functions
Show answer

Answer: B. _safeMint calls onERC721Received on the receiver before minted is set, so the attacker re-enters mint() from that callback

_safeMint (and safeTransferFrom) call onERC721Received on contract receivers, which is an external call to attacker code. Because minted is updated after that call, the attacker can call mint() again from the callback and pass the check each time. Update state before the mint (checks-effects-interactions) or add a reentrancy guard.

44. Using a signature as a nonce

A contract prevents replay by storing used[keccak256(signature)] = true. Why can an attacker still reuse a valid signature?

  1. A.keccak256 of a signature can collide easily
  2. B.Signatures expire after one block
  3. C.ECDSA signatures are malleable: (r, s) can be changed to (r, n - s) with a flipped v, which is a different byte string that recovers the same signer
  4. D.The contract cannot read the signature bytes
Show answer

Answer: C. ECDSA signatures are malleable: (r, s) can be changed to (r, n - s) with a flipped v, which is a different byte string that recovers the same signer

For secp256k1, both s and n - s give a valid signature for the same message and signer. So the attacker produces a second, different signature and its hash is not in the used set. Track replay with a nonce or the message hash instead, and use OpenZeppelin ECDSA, which rejects high-s values.

45. Hash collision with encodePacked

An allowlist checks keccak256(abi.encodePacked(name, role)) against signed hashes, where name and role are both strings. What can go wrong?

  1. A.Different pairs like ("ad", "min") and ("a", "dmin") produce the same packed bytes and the same hash, so one signature can authorize a different pair
  2. B.abi.encodePacked cannot take strings
  3. C.keccak256 returns a different hash each time for strings
  4. D.Packed encoding adds random padding, so hashes never match
Show answer

Answer: A. Different pairs like ("ad", "min") and ("a", "dmin") produce the same packed bytes and the same hash, so one signature can authorize a different pair

abi.encodePacked concatenates dynamic types with no length prefix, so the boundary between two strings is lost. Any split of the same characters hashes the same. Use abi.encode, which includes offsets and lengths, or structured EIP-712 hashing.

46. Constant product swap output

A constant product AMM (x * y = k) pool holds 100 ETH and 200,000 USDC. Ignoring fees, about how much USDC does a trader get for selling 10 ETH?

  1. A.About 18,182 USDC
  2. B.Exactly 20,000 USDC
  3. C.About 22,222 USDC
  4. D.About 19,900 USDC
Show answer

Answer: A. About 18,182 USDC

k = 100 * 200,000 = 20,000,000. After the trade the pool has 110 ETH, so it must keep 20,000,000 / 110 ≈ 181,818 USDC, and the trader receives about 200,000 - 181,818 = 18,182 USDC. The gap from the spot price of 20,000 is price impact, which grows as the trade gets larger relative to the pool.

47. Why transparent proxies split callers

Why does the transparent proxy pattern route admin calls to the proxy and all other calls to the implementation?

  1. A.To make admin calls cheaper
  2. B.To let the admin skip gas fees
  3. C.Because implementations cannot have external functions
  4. D.To avoid function selector clashes: if a proxy function and an implementation function share a 4-byte selector, users could accidentally trigger proxy admin logic
Show answer

Answer: D. To avoid function selector clashes: if a proxy function and an implementation function share a 4-byte selector, users could accidentally trigger proxy admin logic

Selectors are only 4 bytes, so two different functions can share one. The transparent pattern removes the ambiguity: the admin only reaches proxy functions, and everyone else is always forwarded. The cost is an extra admin check on every call, which is one reason UUPS became popular.

48. Expensive loop over storage

Which change saves the most gas in this function?

uint256[] public rewards;
uint256 public total;

function sum() external {
    for (uint256 i = 0; i < rewards.length; i++) {
        total += rewards[i];
    }
}
  1. A.Change i++ to ++i
  2. B.Load total into a local variable, read rewards.length once, add in memory, and write total to storage once at the end
  3. C.Make rewards private
  4. D.Use uint8 for i to save space
Show answer

Answer: B. Load total into a local variable, read rewards.length once, add in memory, and write total to storage once at the end

Each loop iteration currently reads rewards.length, reads total, and writes total, and storage access costs far more than stack or memory (cold SLOAD is 2,100 gas, and SSTORE is thousands). Caching values locally and doing one SSTORE at the end removes most of that cost. ++i saves only a few gas since 0.8.22, and a uint8 counter can even cost more.

49. Impermanent loss at a 4x price move

You deposit equal value of ETH and USDC into a 50/50 constant-product pool. ETH's price then rises 4x. Ignoring fees, how does your position compare with just holding?

  1. A.About 20% less than holding
  2. B.About 4% less than holding
  3. C.About 50% less than holding
  4. D.The same as holding
Show answer

Answer: A. About 20% less than holding

For a price ratio r, the loss versus holding is 2√r/(1+r) − 1. With r = 4 that is 2×2/5 − 1 = −0.2, so 20% less. The pool sells ETH as it rises, leaving you with less of the asset that went up. Fees may or may not make up for it.

50. Changing an allowance from 100 to 50

Alice approved Bob for 100 tokens. She now calls `approve(bob, 50)`. Bob watches the mempool. What is the worst case?

  1. A.Bob can spend at most 50 after the change
  2. B.Bob spends the 100 first, then the new 50, taking 150 in total
  3. C.The second approve reverts while the first is unused
  4. D.Bob's spend reverts because the allowances clash
Show answer

Answer: B. Bob spends the 100 first, then the new 50, taking 150 in total

approve overwrites the allowance. If Bob front-runs the change with transferFrom of 100, the new approve then sets a fresh 50 that he can also spend. Setting to zero first, using increase/decrease functions, or permit-style one-off approvals reduce this risk.

51. When collateral can be frozen

Your protocol holds users' USDC in one pool contract. Circle can freeze any address. What risk should your design consider?

  1. A.If the pool is frozen, every user's USDC is stuck at once
  2. B.Frozen USDC is automatically refunded to users
  3. C.USDC cannot be frozen once it is inside a contract
  4. D.Freezing only affects addresses outside the US
Show answer

Answer: A. If the pool is frozen, every user's USDC is stuck at once

USDC and USDT both have admin functions to blacklist addresses, including contracts. A pool holding everyone's funds could be frozen after a sanctions action or compromise. Teams weigh this when choosing collateral, splitting funds and planning governance responses.

52. A compromised npm package in a dapp

A popular wallet-connector npm package was briefly replaced with code that pops up a fake approval. What protects your dapp best against this kind of attack?

  1. A.Pinned versions, reviewed updates and a strict CSP
  2. B.Using only HTTPS for the whole website
  3. C.Asking users to check the URL bar every time
  4. D.Moving the dapp to a different hosting provider
Show answer

Answer: A. Pinned versions, reviewed updates and a strict CSP

Supply-chain attacks inject malicious code through dependencies, as with the Ledger Connect Kit incident in 2023. Pinned versions, lockfiles, delayed adoption of new releases, subresource integrity for CDN scripts and a content security policy limit what bad code can load or call. HTTPS does not help if the code itself is bad.

53. Modifier order and reentrancy

A function is declared as function claim() external updateReward(msg.sender) nonReentrant. updateReward calls an external rewards contract. Why is the order a problem?

  1. A.updateReward runs before the lock, so its call can re-enter
  2. B.Modifiers always run after the function body finishes
  3. C.nonReentrant only works when it is the last modifier
  4. D.Solidity runs modifiers in a random order each call
Show answer

Answer: A. updateReward runs before the lock, so its call can re-enter

Modifiers run left to right, wrapping the function. Here updateReward makes its external call before nonReentrant sets the lock, so a callback can re-enter claim or other guarded functions. Put nonReentrant first so the lock covers everything, and avoid external calls in modifiers.

54. Very large memory arrays

A function builds a huge in-memory array and gas use grows much faster than the array size. Why?

  1. A.Each memory word is written to storage too
  2. B.Memory reads become cold accesses after 1 KB
  3. C.The optimizer turns off for large arrays
  4. D.Memory expansion cost grows with the square of size
Show answer

Answer: D. Memory expansion cost grows with the square of size

Memory costs 3 gas per 32-byte word plus words^2 / 512, so the quadratic term dominates for large sizes. Gas therefore grows faster than linearly. Process data in chunks, avoid copying large arrays, or use calldata where possible.

55. Price that comes out as zero

This function returns 0 for amount = 5. Why, and what is the fix?

// price has 2 decimals: 1 unit = 100
function cost(uint256 amount) public pure returns (uint256) {
    return amount / 10 * 100;
}
  1. A.Solidity rounds 0.5 down only for pure functions
  2. B.The literal 100 must be written as 100e0
  3. C.5 / 10 truncates to 0 first; compute amount * 100 / 10
  4. D.The return type should be int256 for fractions
Show answer

Answer: C. 5 / 10 truncates to 0 first; compute amount * 100 / 10

Integer division truncates, so 5 / 10 is 0 and the multiplication cannot recover it. Multiplying first gives 500 / 10 = 50. For large values, multiplying first can overflow, so libraries offer mulDiv(a, b, c) that computes a x b / c with full 512-bit precision.

56. Indexed strings in events

An event declares string indexed name. An indexer reads the log and wants the actual name text. What does it find?

  1. A.The full string stored in the topic
  2. B.The first 32 bytes of the string
  3. C.Only keccak256 of the string in the topic
  4. D.The string length and the first character
Show answer

Answer: C. Only keccak256 of the string in the topic

Topics are 32 bytes, so indexed dynamic types like string, bytes and arrays are stored as their keccak256 hash. You can filter by an exact value, but you cannot read the original text from the topic. If you need both, emit the string twice: once indexed and once as a non-indexed field.

57. Storing claim flags cheaply

An airdrop must record whether each of 100,000 indexes has claimed. Which approach uses the least storage gas?

  1. A.A mapping(uint256 => uint256) bitmap: 256 flags per slot
  2. B.A mapping(uint256 => bool), one slot per index
  3. C.A bool[] array with one entry per index
  4. D.A string that lists all claimed indexes
Show answer

Answer: A. A mapping(uint256 => uint256) bitmap: 256 flags per slot

A bool in its own mapping entry uses a full 32-byte slot, so each first claim pays about 20,000 gas. A bitmap stores 256 flags in one word: word = index / 256, bit = index % 256, set with word |= 1 << bit. Only the first claim per word pays the zero-to-non-zero cost. OpenZeppelin's BitMaps does this.

58. A try/catch that still reverts

A contract wraps an external call in try/catch with a catch-all clause. The callee returns successfully but with malformed return data. What happens?

  1. A.The catch clause runs with the decode error
  2. B.Decoding fails in the caller and the whole call reverts
  3. C.The function continues with zero values
  4. D.The callee is retried once automatically
Show answer

Answer: B. Decoding fails in the caller and the whole call reverts

try/catch only catches reverts inside the called contract. Decoding the return data happens in the caller, and if it fails, that revert is not caught. Calling an address with no code can also slip past. Use a low-level call and decode carefully when the target is untrusted.

59. A catch clause that does not match

A try/catch has only catch Error(string memory reason). The callee reverts with a custom error InsufficientBalance(). What happens?

  1. A.Nothing matches, so the revert bubbles up
  2. B.The Error clause runs with an empty reason
  3. C.The custom error is turned into a string
  4. D.The transaction succeeds with no effect
Show answer

Answer: A. Nothing matches, so the revert bubbles up

catch Error(string) only matches revert("...") and require with a message. Panics need catch Panic(uint256), and custom errors need catch (bytes memory data) or a bare catch. With no matching clause, the error propagates and the caller reverts.

60. Secret user writing to an unclassified file

Under the Bell–LaPadula model, a user cleared for Secret tries to write into an Unclassified document. What does the model say?

  1. A.Allowed: higher clearance can always write anywhere
  2. B.Allowed: only reading down is restricted by the model
  3. C.Denied: no write down, to stop leaks to lower levels
  4. D.Denied: no read up, to protect higher levels
Show answer

Answer: C. Denied: no write down, to stop leaks to lower levels

Bell–LaPadula protects confidentiality with "no read up" (simple security property) and "no write down" (star property). Writing Secret knowledge into an Unclassified file could leak it, so it is denied. The Biba model does the reverse for integrity.

Ready to test yourself?

Take a 15-question Blockchain MCQ test with a score at the end, or practise the full Blockchain question bank and earn points on the leaderboard.