Top 10 Solidity interview questions to help you prepare for your next Solidity technical initerview. Join your dream team as a smart contract developer!
Table of Contents
If you’re preparing for a Solidity technical interview, it can be challenging to find relevant questions to study and practice as a web3 software developer, especially when the language has barely existed for a decade.
In this article, we’ve collected the top 10 Solidity interview questions commonly asked in technical interviews at some of the biggest blockchain protocols.
This tailored list of questions will allow you to showcase your Solidity skill without stumbling on niche "gotcha" type questions. The focus leans toward open-ended, topic based discussion rather than narrow questions.
Aspiring Solidity developers may use these questions to test their knowledge and prepare for their next interview. Hiring managers can use this list of Solidity interview questions as a roadmap to identify novice developers and as a stage for experienced smart contract developers to shine.
Each question includes an example answer and brief explanation that details the purpose behind it.
Solidity interview questions
1. What is typically needed to interact with a smart contract?
The deployed contract address.
The contract's ABI (Application binary interface).*
A provider for read-only interactions. A signer for state-changing interactions.
*Technically speaking, if you can read the EVM opcodes then you don’t need an ABI. You can manually create the calldata with tools like Foundry’s cast. Despite the simplicity of the question, it effectively probes into the basic knowledge required for solidity development. Our beginner course details contract interactions with Remix and gives more information on contract ABI.
2. Describe function keywords and data structures specific to Solidity.
Visibility keywords
Public: Callable from anywhere.
Private: Callable only within the contract.
Internal: Callable within the contract and inheriting contracts.
External: Callable only from outside the contract.
Mutability & Modifier keywords
View: Prohibited from writing to state; may only read state variables.
Pure: Prohibited from reading or writing to state.
Payable: Allows the native gas token to be received directly via msg.value in the function call.
Virtual: Declares a function as overridable (changeable in child contracts).
Override: Declares a function is an override of a virtual function.
Custom Modifiers
Code that is executed before, after, or even during a function body. Often used as a preliminary security check.
Data structures
State variable: On chain storage, unless labeled a constant or immutable.
Address: A smart contract address or user’s externally owned account (EOA). Can be typecast to uint160 or bytes20.
Enum: Custom exhaustible types that compile into integers.
Struct: Structured blueprint for similar data.
Mapping: Key-value storage similar to a hash table. Values for all keys default as the zero value for their type.
Events/Errors: Readable information exposed on chain to easily parse transactions.
There's a lot more to being a good Solidity developer than just understanding keywords, but having a good grasp of the landscape is naturally important. A more comprehensive walkthrough is found in our Solidity Smart Contract Development course.
3. Define interfaces, abstract contracts, and libraries.
An interface defines functions without implementation so they adhere to a specific structure. They are not deployable contracts.
An abstract contract is a base contract that has at least one function without an implementation. It's used as a template for other contracts to inherit. It cannot be deployed.
A library is useful for recurrent code and may be deployed if it contains external functions. Contracts use delegatecall to call the libraries external functions. A library that contains only internal functions is not deployed and does not need to use delegatecall due to the absence of state interactions.
Solidity is unlike other languages due to its immutable nature. It must be written in a concise, clear manner with focus on minimizing contracts, state variables, functions, and interactions. Bugs arise exponentially as a codebase grows.
A strong understanding of these building blocks is important to avoid a big heaping plate of spaghetti code manifesting in larger projects.
4. Name common EIPs and briefly describe their purpose and functionality.
EIP-20: Standardized the structure for many identical tokens (fungible).
EIP-721: Standardized the structure for unique tokens (NFTs).
EIP-1155: Standardized the structure for the multi-token solution (NFT and ERC-20 features combined).
EIP-777: Token with hooks.
EIP-1559: Restructured fee mechanics with a burned base fee, priority fee, and max fee.
EIP-4626: Standardized vaults for deposits and withdrawals.
EIP-137: Ethereum Name Service (ENS), mapping readable names to underlying addresses.
EIP-2612: Permit functionality providing single actor gasless approvals.
A developer worth their salt should be able to rattle off common EIPs very quickly. If they are struggling to name examples beyond basic tokens, then they haven't explored many of the core concepts that DeFi uses to operate. A Solidity developer that has experience with relevant EIPs is valuable.
5. How do proxy patterns work? Describe the common patterns.
Smart contracts are immutable unless they leverage a proxy pattern. Proxy patterns unlock the ability to change an implementation contract address and make the contract upgradable. All patterns use delegatecall to call the implementation while maintaining state in the centralized proxy. Implementations use initializers instead of constructors. An admin is needed to execute the change of an implementation address.
UUPS (Universal Upgradeable Proxy Standard): The upgrade and admin logic is in the implementation contract.
Transparent Proxy: The upgrade logic is in the proxy contract with a clear separation between the proxy and implementation.
Diamond Pattern: Allows for the creation of multiple implementation contracts in the form of facets. The diamond is the proxy.
Beacon: Uses a central beacon to track the implementation for multiple proxies. Efficient for multiple proxy upgrades but rarely used in practice.
Function selector clashes, storage collisions, and lack of initialization are just some of the bugs that can be generated while developing with proxy patterns. Developers and security enthusiasts unfamiliar with these concepts may want to look at this comprehensive deep dive into these proxy patterns. Understanding proxies at a deep level is critical to ensuring upgradable projects stay bug free before, during, and after upgrades.
6. Describe the lifecycle of a smart contract deployed on an EVM-compatible L1, from compilation to user interactions.
An EVM language such as Solidity, Yul, Vyper, or Huff can be locally compiled to produce the raw bytecode and ABI for the contract. After compilation, a contract's bytecode can be deployed via a signer and RPC provider. The signer's private key is required to execute transactions on behalf of its public key, while the RPC provider broadcasts the transaction to the network of validators.
The consensus agents in proof of stake networks are called validators. Validators are nodes running full blockchain client software that includes an EVM implementation. They require staked tokens to operate. Validators maintain the chain's current state, propose and validate new blocks, and execute received transactions.
During deployment, a transaction containing the contract's bytecode and constructor parameters is broadcast to the network and enters the mempool. Validators select transactions from the mempool for inclusion in new blocks. The mempool transparently shows pending transactions which facilitates MEV opportunities. The CREATE opcode is used to generate an address which points to the contract's bytecode and storage.
After deployment, any EOA or smart contract can interact with the exposed functions of the contract to view and update the on-chain state. ABIs generated during compilation are often used for frontend interactions with contracts.
A developer who can easily articulate the bigger picture of web3 concepts is likely to be genuinely passionate and knowledgeable about the ecosystem as a whole.
7. What is fuzzing and formal verification? Write a basic stateful fuzzing test.
Fuzzing is feeding random or semi-random data to a system in an attempt to find detrimental inputs that break invariants. Invariants are properties of the system that must always remain true. Formal verification is the method that deconstructs the underlying logic into a mathematical proof, to prove or disprove that an invariant will hold.
A stateful fuzzing test randomly calls state changing functions in order to travel through unique states in the system, which are then checked through invariant_ or statefulFuzz_ labeled functions to ensure the declared properties and invariants hold. Below is a mock example using the modified Counter contract of an initialized Foundry project.
contract Counter {
uint256 public number;
uint256 public constant UPPER_LIMIT = 100;
function setNumber(uint256 newNumber) public {
require(newNumber <= UPPER_LIMIT, "Number too high");
number = newNumber;
}
function increment() public {
require(number < UPPER_LIMIT, "limit reached");
number++;
}
}
contract CounterTest is StdInvariant, Test {
Counter public counter;
function setUp() public {
counter = new Counter();
// Forces fuzzer to focus on this contract for testing.
targetContract(address(counter));
}
// Required `invariant_` prefix to denote invariant related
// conditions that will be run between the state changing functions.
function invariant_numberNeverExceedsLimit() public {
assertTrue(counter.number() <= counter.UPPER_LIMIT());
}
The ability to understand and discuss testing techniques is related to the maturity of a developer. Rigorously trying to break Solidity code is especially important because user funds are directly intertwined with the code. If faulty code is published, malicious actors will take advantage of it to steal funds. Smart contract security reviews that find many bugs in poor code can greatly increase the cost of development if the codebase needs to be scrapped or drastically changed.
8. How are contract addresses and function selectors produced? Where are function selectors placed in calldata?
Function selectors are defined as the first 4 bytes from the Keccak256 hash of the function signature. A selector is placed at the beginning of the calldata. Notably, we can easily use Foundry’s cast sig command to produce the function selector from a function signature. Running cast sig "transfer(address,uint256)" will successfully produce the correct function selector 0xa9059cbb.
CREATE: The default method for contract address creation. The address is produced by taking the last 20 bytes from the resulting hash of the encoded sender and their current nonce.
CREATE2: Enables pre-computation of contract address. The address is produced by taking the last 20 bytes from the resulting hash of the sender address, a 32 byte salt, and hash of initialization code. The salt allows for crafting a precomputed desired address.
Understanding smart contract address generation and recognizing function selectors and other information in calldata should not be foreign material.
9. Define Yul and describe a simple token transfer or gas optimization in assembly. Describe the free memory pointer.
Yul is an intermediary language that is syntactically closer to opcode instructions than Solidity.
A token transfer would sload sender and receiver balances, use lt comparator to determine if the sender has enough tokens, update balances based on the amount via sstore, emit an event using log3 for the two addresses and amount, and return true on success using an mstore and return.
A straightforward gas saving technique uses an unchecked assembly block for calculations where the result cannot overflow.
The free memory pointer (FMP) keeps track of where new data can go by pointing to the next available space in memory. It's always located in memory at 0x40, after the scratch space and before the zero slot. It initially points to 0x80 as the first available location. Because Solidity doesn't free memory, the FMP automatically moves in 32 byte chunks every time new data needs to be stored in memory.
The FMP needs to be restored when you've manually adjusted it during a function to ensure that future operations don’t overwrite important data.
Having a grasp of assembly with respect to Solidity can be useful for crafting gas optimizations, understanding the result of bitwise operations, and effectively reading or integrating libraries that leverage Yul for efficiency.
10. List common Solidity vulnerabilities and techniques to combat them.
This is where a Solidity developer can really shine. Articulating proper defenses against the plethora of attack vectors is key to keeping contracts safe. It's a green flag if you compete in public security audit contests, bug bounties, or perform private security reviews. The ability to have a security focused mindset while developing smart contracts is highly valuable.
11. [BONUS] What projects have you built? What are some favorite bugs you've found? Are you passionate or advanced in a specific area?
Randomness or price feed oracle integration, borrowing dApp integrations, DEX integrations, cross chain projects, projects built with various EIPs, zero knowledge apps, library and tooling contributions.
Solo or interesting bugs found in contests/bug bounties/private security reviews.
This question is arguably the most important. Exploring a developer's finished products, additional accomplishments, and what they’re passionate about can show a clearer picture of their experience and tendencies.
Finishing thoughts
While it's difficult to traverse the entire landscape of Solidity in 10 interview questions, this aims to act as an effective guide to extract the maximum amount of relevant Solidity knowledge per question. As a Solidity developer hopefully you learned something new and feel more prepared for the next interview. For readers who are hiring managers, perhaps this can serve as a foundational beacon of information used to scout your next Solidity dream team.
Anybody with a passion for web3 development and security should join Cyfrin Updraft to jumpstart their learning or dust off the cobwebs before their next interview.
Cyfrin Updraft
Learn smart contract development, how to write secure smart contracts, and scalable protocols from world's leading experts.