# Solidity Developers के लिए Top 30 Web3 Interview Questions
Dozens candidates interview करने और top Web3 companies की hiring practices review करने के बाद, यहां वे 30 questions हैं जो सबसे frequently appear होते हैं — answers के साथ जो आपको stand out करने में help करेंगे।
Solidity Basics (Questions 1-8)
1. memory, storage, और calldata में क्या difference है?
Answer:
- Storage: Blockchain पर stored persistent data। सबसे expensive। State variables by default storage use करते हैं।
- Memory: Temporary data जो function execution के दौरान exist करता है। External function calls के between erase हो जाता है। Storage से cheaper।
- Calldata: Function parameters के लिए read-only temporary data। Memory से cheaper। सिर्फ external function parameters के लिए available।
Example:
contract DataLocations {
uint[] public storageArray; // storage by default
function processArray(uint[] calldata data) external {
// data calldata में है (read-only, cheapest)
uint[] memory tempArray = new uint[](data.length); // memory
storageArray = tempArray; // storage में copy होता है
}
}
Follow-up वे पूछ सकते हैं: "Return values के लिए calldata क्यों use नहीं कर सकते?"
Answer: Calldata input-only है। Return values memory use करती हैं।
---
2. ETH send करने के लिए transfer, send, और call में difference explain करें।
Answer:
transfer(amount): ETH send करता है, 2300 gas forward करता है, failure पर revert करता है। ❌ Avoid करें (gas cost changes के साथ break होता है)।
send(amount): ETH send करता है, 2300 gas forward करता है, failure परfalsereturn करता है। ❌ Avoid करें (transfer जैसे issues)।
call{value: amount}(""): ETH send करता है, सभी available gas forward करता है,(bool success, bytes memory data)return करता है। ✅ Recommended।
Best practice (2026):
(bool success, ) = recipient.call{value: amount}("");
require(success, "ETH transfer failed");
वे यह क्यों पूछते हैं: Test करते हैं कि आप modern best practices के साथ up to date हैं।
---
3. Function visibility specifiers क्या हैं और हर एक को कब use करें?
Answer:
public: कहीं से भी callable (externally, internally, derived contracts)। State variables के लिए automatic getter generate करता है।
external: सिर्फ contract के बाहर से callable। Large arrays के लिए ज्यादा gas-efficient (calldata use करता है)।
internal: सिर्फ contract के भीतर या derived contracts में callable।
private: सिर्फ defining contract के भीतर callable (derived contracts में नहीं)।
Pro tip: Functions के लिए external use करें जो internally कभी call नहीं होते — gas save करता है।
---
4. view, pure, और no modifier में क्या difference है?
Answer:
- No modifier: State को READ और modify दोनों कर सकता है। Transaction में call करने पर gas cost करता है।
view: State को READ कर सकता है पर modify नहीं कर सकता। Externally (off-chain) call करने पर free। Transaction में दूसरे function द्वारा call करने पर gas cost करता है।
pure: State को READ या modify नहीं कर सकता। सिर्फ function parameters और local variables use करता है।
Common mistake: Function को view mark करना जब वह दूसरे contract को call करता है (जो state change कर सकता है) — यह recent Solidity versions में compile fail करेगा।
---
5. delegatecall call से कैसे differ करता है?
Answer:
call: CALLED contract के context में code execute करता है (उसकी storage use करता है,msg.senderchange होता है)।
delegatecall: CALLING contract के context में code execute करता है (caller की storage use करता है,msg.senderpreserved रहता है)।
Use case: Proxy patterns, upgradeable contracts, libraries।
Security risk: Storage layout proxy और implementation के between EXACTLY match होना चाहिए। Misalignment = catastrophic bugs।
// Proxy contract
contract Proxy {
address public implementation;
fallback() external payable {
address impl = implementation;
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), impl, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
}
---
6. Solidity में == और = में क्या difference है?
Answer:
=: Assignment operator (value set करता है)।
==: Comparison operator (equality check करता है)।
वे यह क्यों पूछते हैं: Surprisingly common bug। Solidity का compiler अब conditionals में assignments के बारे में warn करता है, पर interviewers अभी भी यह test करते हैं।
---
7. Events क्या हैं और वे क्यों important हैं?
Answer:
Events logs emit करने का एक way हैं जो blockchain के transaction receipt में stored होते हैं (contract storage में नहीं)। वे:
- Storage से cheaper (SSTORE 20k gas cost करता है, LOG ~375-1500 gas per event)।
- Off-chain accessible JSON-RPC और indexing services (The Graph, Etherscan) के via।
- On-chain accessible नहीं (दूसरे contracts events read नहीं कर सकते)।
Use cases:
- State change notifications (Transfer, Approval)
- dApps के लिए off-chain indexing
- Audit trails
event Transfer(address indexed from, address indexed to, uint256 value);
function transfer(address to, uint256 amount) public {
balances[msg.sender] -= amount;
balances[to] += amount;
emit Transfer(msg.sender, to, amount); // ✅ हमेशा state changes के बाद emit करें
}
Follow-up: "indexed parameters क्यों use करें?"
Answer: Events को filterable बनाता है। Max 3 indexed parameters per event।
---
8. Modifiers क्या हैं और उन्हें कब use करना चाहिए?
Answer:
Modifiers reusable code हैं जो function से before या after run होता है। Common use: access control, validation, reentrancy guards।
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_; // Function body यहां execute होता है
}
function withdraw() external onlyOwner {
// Only owner इसे call कर सकता है
}
Advanced tip: _; placeholder determine करता है कि function body कब run होगा। आप इसके बाद code रख सकते हैं:
modifier checkInvariant() {
_;
assert(balance >= reserveBalance); // Function के AFTER run होता है
}
---
Security (Questions 9-16)
9. Reentrancy explain करें और इसे कैसे prevent करें।
Answer:
Reentrancy तब occur होता है जब एक contract external contract को call करता है, जो फिर original contract को वापस call करता है first execution complete होने से पहले।
Classic example (vulnerable):
function withdraw(uint amount) public {
require(balances[msg.sender] >= amount);
(bool success, ) = msg.sender.call{value: amount}(""); // 🚨 State update से BEFORE external call
require(success);
balances[msg.sender] -= amount; // 🚨 State बहुत late update हुआ
}
Attack: Attacker की fallback function balances update होने से पहले फिर से withdraw() call करती है।
Fixes:
function withdraw(uint amount) public {
require(balances[msg.sender] >= amount); // Check
balances[msg.sender] -= amount; // Effect
(bool success, ) = msg.sender.call{value: amount}(""); // Interaction
require(success);
}
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract Safe is ReentrancyGuard {
function withdraw(uint amount) public nonReentrant {
// Protected
}
}
---
10. Integer overflow/underflow क्या है और Solidity 0.8+ इसे कैसे handle करता है?
Answer:
Pre-0.8: Integers silently wrap around होते थे।
uint8 x = 255;
x += 1; // 0 बन जाता है (overflow)
Solidity 0.8+: Built-in overflow/underflow protection। Overflow पर automatically revert करता है।
unchecked कब use करें: जब आप certain हैं कि overflow impossible है और gas save करना चाहते हैं।
function increment(uint x) public pure returns (uint) {
unchecked { return x + 1; } // ~20 gas save करता है, पर dangerous अगर x type(uint).max हो सकता है
}
---
11. Front-running attack क्या है?
Answer:
एक attacker mempool monitor करता है, आपका transaction देखता है, और higher gas price के साथ similar transaction submit करता है ताकि आपसे पहले execute हो।
Example: आप एक profitable DEX arbitrage opportunity देखते हैं और transaction submit करते हैं। MEV bot इसे देखता है, 10x gas price के साथ आपका transaction copy करता है, profit steal कर लेता है।
Mitigations:
- Commit-reveal schemes (पहले hash submit करें, बाद में reveal करें)
- Private mempools (Flashbots)
- Slippage protection (limit orders)
- Time-locks (execution delay करें)
---
12. tx.origin क्या है और authentication के लिए इसे क्यों use नहीं करना चाहिए?
Answer:
msg.sender: Immediate caller (contract या EOA हो सकता है)।
tx.origin: Original EOA जिसने transaction chain initiate की।
यह क्यों dangerous है:
// 🚨 VULNERABLE
function withdraw() public {
require(tx.origin == owner); // Attacker owner को malicious contract call करने के लिए trick करता है
payable(owner).transfer(address(this).balance);
}
Attack: Attacker malicious contract deploy करता है जो आपकी withdraw() call करता है। अगर owner attacker के contract के साथ interact करता है, tx.origin अभी भी owner है, इसलिए check pass हो जाता है।
Fix: Authentication के लिए हमेशा msg.sender use करें।
---
13. Flash loan attack क्या है?
Answer:
Flash loans single transaction के भीतर unlimited funds borrow करने allow करते हैं (transaction end होने से पहले repay करना होता है)।
Attack vector: Borrowed funds use करके protocol state (e.g., oracle prices, liquidity pools) manipulate करना, manipulated state exploit करना, profit लेना, funds return करना।
Example: 100M USDC borrow करें, low-liquidity pool में dump करके price crash करें, lending protocol में positions liquidate करें, profit लें, loan repay करें।
Defense:
- TWAP (Time-Weighted Average Price) oracles
- Liquidity depth checks
- Rate limiting
- Reentrancy guards
---
14. Access control vulnerabilities क्या हैं?
Answer:
Sensitive functions पर missing या improper onlyOwner/role checks।
Example:
// 🚨 VULNERABLE (कोई भी mint कर सकता है)
function mint(address to, uint amount) public {
_mint(to, amount);
}
Fix: OpenZeppelin की Ownable या AccessControl use करें।
---
15. assert और require में क्या difference है?
Answer (pre-0.8):
require: Failure पर remaining gas refund करता है। Input validation के लिए।
assert: Failure पर सारी gas consume करता है। Invariant checks के लिए (कभी fail नहीं होना चाहिए)।
Solidity 0.8+: दोनों gas refund करते हैं। assert अभी भी सिर्फ internal errors/invariants के लिए use होना चाहिए।
function withdraw(uint amount) public {
require(amount <= balance, "Insufficient balance"); // User error
balance -= amount;
assert(balance >= 0); // कभी fail नहीं होना चाहिए (invariant)
}
---
16. selfdestruct क्या है और यह क्यों dangerous है?
Answer:
selfdestruct(address payable recipient) contract delete करता है और उसका ETH balance recipient को send करता है।
Dangers:
- Forcibly ETH send करता है recipient को (payable check bypass करता है, invariants break कर सकता है)
- Code permanently destroy करता है (पर storage on-chain remain करता है)
- Deletion के बाद external contracts द्वारा call नहीं हो सकता (composability break करता है)
2026 note: EIP-6780 (Cancun upgrade) selfdestruct restrict करता है — यह अब सिर्फ funds send करता है, code delete नहीं करता unless same transaction में creation के साथ call हो।
---
Gas Optimization (Questions 17-22)
17. Solidity में gas कैसे optimize कर सकते हैं?
Key techniques:
uint256>uint8: Smaller types extra gas cost करते हैं (type conversion)। Packed storage के अलावाuint256use करें।
calldata>memory: External functions के लिए array parameters।
++i>i++: Loops में post-increment avoid करें।
- Caching: Storage variables को memory में cache करें loops में।
- Short-circuit evaluation:
&&और||में cheaper conditions पहले रखें।
external>public: अगर internally call नहीं होता।
- Immutable और constant: जब possible हो।
Example:
// ❌ Expensive
for (uint i = 0; i < arr.length; i++) {
total += arr[i];
}
// ✅ Optimized
uint length = arr.length; // Cache
for (uint i; i < length; ) {
total += arr[i];
unchecked { ++i; }
}
---
18. Storage packing क्या है?
Answer:
Solidity variables को 32-byte slots में store करता है। Multiple variables एक slot share कर सकते हैं अगर वे combined < 32 bytes हों।
Example:
// ❌ 3 storage slots use करता है
uint256 a; // Slot 0
uint128 b; // Slot 1
uint128 c; // Slot 2
// ✅ 2 storage slots use करता है (gas save)
uint256 a; // Slot 0
uint128 b; // Slot 1 (first half)
uint128 c; // Slot 1 (second half)
Savings: SSTORE 20k gas first write के लिए, 5k updates के लिए।
---
19. Loops gas कैसे optimize करें?
Techniques:
- Array length cache करें
++iunchecked block में
- Storage reads minimize करें
- Fixed-size arrays prefer करें जब size known हो
// ❌ Expensive
for (uint i = 0; i < items.length; i++) {
process(items[i]);
}
// ✅ Optimized
uint length = items.length;
for (uint i; i < length; ) {
process(items[i]);
unchecked { ++i; }
}
---
20. mapping vs array — gas perspective से कब use करें?
Answer:
- Mapping: O(1) access। Delete operations gas-efficient। बड़े datasets के लिए better। Iterate नहीं कर सकते।
- Array: Iteration support करता है। Small datasets के लिए better। Push/pop operations costly हो सकते हैं।
Use mapping when: Fixed lookups, large datasets, deletion frequent है।
Use array when: Iteration चाहिए, small known size, ordering matter करता है।
---
21. Custom errors vs require strings — कौन सा cheaper है?
Answer:
Custom errors (Solidity 0.8.4+) significantly cheaper हैं।
// ❌ Expensive (~50 bytes for string)
require(msg.sender == owner, "Only owner can call this function");
// ✅ Cheaper (~22 bytes)
error NotOwner();
if (msg.sender != owner) revert NotOwner();
Savings: ~800 gas per error message।
---
22. Function को payable बनाना gas क्यों save करता है?
Answer:
Non-payable functions check add करते हैं कि msg.value == 0। यह check ~24 gas cost करता है।
अगर function ETH receive नहीं करेगा, फिर भी payable mark करने से यह check remove होता है।
⚠️ Caution: सिर्फ तब use करें जब 100% certain हों कि accidental ETH sends issue नहीं हैं।
---
EVM Internals (Questions 23-26)
23. EVM storage layout कैसे काम करता है?
Answer:
- State variables: 32-byte slots में stored (slot 0, 1, 2...)
- Mappings:
keccak256(key . slot)पर stored
- Dynamic arrays: Length slot में stored, elements
keccak256(slot) + indexपर
Example:
contract StorageLayout {
uint256 a; // Slot 0
uint256 b; // Slot 1
mapping(address => uint256) balances; // Slot 2 (empty), actual data keccak256(address . 2) पर
uint256[] arr; // Slot 3 (length), elements keccak256(3) + index पर
}
---
24. STATICCALL opcode क्या है?
Answer:
CALL जैसा पर state modifications prevent करता है। view और pure functions STATICCALL use करते हैं।
Why it matters: यदि view function state modify करने की कोशिश करता है, STATICCALL revert करेगा।
---
25. Contract bytecode में क्या difference है: creation code vs runtime code?
Answer:
- Creation code: Constructor execute करता है, runtime code को blockchain पर store करता है।
- Runtime code: वास्तविक contract logic। यही calls के लिए execute होता है।
Interview tip: "Deploying contract सिर्फ runtime code store करता है, creation code नहीं" mention करना shows depth।
---
26. EVM में gas refund कैसे काम करता है?
Answer:
- Storage clearing (SSTORE 0): 15k gas refund (पहले 24k था, pre-London fork)
SELFDESTRUCT: 24k refund (अब EIP-6780 के बाद restricted)
2026 update: Gas refunds को reduced किया गया है DoS attacks prevent करने के लिए। अब max refund transaction के used gas का 20% है।
---
DeFi Protocols (Questions 27-30)
27. AMM (Automated Market Maker) कैसे काम करता है?
Answer:
AMMs constant function formula use करते हैं liquidity pools से trades facilitate करने के लिए।
Uniswap V2 (constant product):
x * y = k
जहां x और y pool में token reserves हैं, k constant है।
Example:
// Pool: 100 ETH, 200,000 USDC → k = 20,000,000
// User 10 ETH swap करता है
// New reserves: 110 ETH, ? USDC
// 110 * newUSDC = 20,000,000
// newUSDC = 181,818 USDC
// User receives: 200,000 - 181,818 = 18,182 USDC
---
28. Impermanent loss क्या है?
Answer:
Impermanent loss वह loss है जो liquidity providers experience करते हैं जब pool में token prices change होती हैं।
Example: आप 1 ETH + 2000 USDC deposit करते हैं (ETH = $2000)। ETH $4000 हो जाता है। अगर आपने simply hold किया होता, आपके पास 1 ETH ($4000) + 2000 USDC = $6000 होता। Pool में, arbitrage के बाद आपके पास ~0.707 ETH + 2828 USDC = ~$5656 है। Loss: $344 (~5.7%)।
Why "impermanent": अगर price original ratio पर लौटती है, loss disappear हो जाता है।
---
29. Flash loans क्या हैं और वे कैसे काम करते हैं?
Answer:
Flash loans uncollateralized loans हैं जो single transaction में borrow और repay होने चाहिए।
Mechanism:
Use cases: Arbitrage, collateral swapping, self-liquidation।
Example (Aave):
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external returns (bool) {
// Borrowed funds के साथ अपनी logic यहां
// ...
// Loan + premium approve करें repayment के लिए
for (uint i = 0; i < assets.length; i++) {
uint amountOwing = amounts[i] + premiums[i];
IERC20(assets[i]).approve(address(POOL), amountOwing);
}
return true;
}
---
30. Oracle problem क्या है और Chainlink इसे कैसे solve करता है?
Answer:
Oracle problem: Blockchains inherently real-world data access नहीं कर सकते (prices, weather, sports scores)। External data source पर rely करना centralization introduce करता है।
Chainlink solution:
- Decentralized oracle network: Multiple independent nodes data provide करते हैं
- Aggregation: Median value use करता है outliers remove करने के लिए
- Reputation system: Reliable nodes reward होते हैं, malicious nodes penalized होते हैं
Example integration:
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract PriceConsumer {
AggregatorV3Interface internal priceFeed;
constructor() {
priceFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419); // ETH/USD
}
function getLatestPrice() public view returns (int) {
(, int price, , , ) = priceFeed.latestRoundData();
return price;
}
}
---
Conclusion
ये 30 questions modern Web3 interviews के core topics cover करते हैं। Key success के लिए:
Practice कहां करें:
Solingo interactive challenges provide करता है जो इन concepts को production-grade code scenarios में test करती हैं।
आपका next interview आपके Solidity mastery showcase करने का मौका है। Good luck! 🚀