The questions focus on Cairo syntax, Starknet development, zero-knowledge proofs, and integration with Ethereum ecosystems. Each answer is concise, practical, and tailored to demonstrate expertise for a Cairo developer role.
Table of Contents
Beginner-Level Questions (1–15)
1. What is Cairo?
Answer: Cairo is a Turing-complete programming language for writing provable programs, optimized for zero-knowledge proofs (ZKPs) like STARKs. It’s used primarily for Starknet smart contracts, enabling scalable and secure computations on Ethereum’s Layer 2.
2. Why is Cairo used for Starknet?
Answer: Cairo is designed to generate efficient STARK proofs, which Starknet uses to batch and verify transactions off-chain, reducing Ethereum mainnet costs and improving scalability while maintaining security.
3. What is Starknet?
Answer: Starknet is a permissionless Layer 2 blockchain on Ethereum that uses STARK proofs for scalability. It supports general-purpose smart contracts written in Cairo, offering low-cost, high-throughput dApp development.
4. How does Cairo differ from Solidity?
Answer:
- Cairo: Focused on provable computation, generates STARK proofs, used for Starknet.
- Solidity: General-purpose language for Ethereum smart contracts, runs on the EVM.
- Cairo emphasizes mathematical correctness and off-chain computation, while Solidity is more flexible for on-chain logic.
5. What is the basic structure of a Cairo program?
Answer: A Cairo program includes:
- Functions: Defined with func and end.
- Modules: Organized with mod for namespacing.
- Imports: Using from … import.
- Hints: Python-like code for guiding proof generation.
- Return Values: Explicitly declared with return.
Example:
cairo
func add(a: felt, b: felt) -> (res: felt) {
return (res=a + b);
}
6. What is a felt in Cairo?
Answer: felt (field element) is Cairo’s primary data type, representing an integer in a finite field (modulo a prime). It’s used for all arithmetic operations and is central to STARK proof generation.
7. How do you install Cairo?
Answer:
- Install prerequisites: Python, Rust, and a package manager (e.g., pip).
- Install the Cairo compiler:
bash
pip install cairo-lang
- Verify with cairo-compile –version.
8. What is the role of hints in Cairo?
Answer: Hints are Python-like code snippets embedded in Cairo programs (enclosed in %{ … %}) that guide the prover without affecting program correctness. They optimize proof generation by providing computational shortcuts.
Example:
cairo
%{
memory[ap] = 42
%}
9. How do you compile a Cairo program?
Answer: Compile a Cairo file (program.cairo) to a JSON representation:
bash
cairo-compile program.cairo --output program.json
The output is used for execution or proof generation.
10. What is the purpose of the alloc function in Cairo?
Answer: alloc allocates memory for arrays or dynamic data structures in Cairo’s memory model. It returns a pointer to the allocated memory.
Example:
cairo
let (ptr: felt*) = alloc();
11. What is a Starknet contract?
Answer: A Starknet contract is a smart contract written in Cairo, deployed on Starknet. It defines storage, functions, and events, leveraging STARK proofs for scalable execution.
12. How do you declare a function in Cairo?
Answer: Use the func keyword, specify parameters, and declare return types:
cairo
func multiply(x: felt, y: felt) -> (result: felt) {
return (result=x * y);
}
13. What is the assert statement in Cairo?
Answer: assert checks a condition and halts execution if false, ensuring program correctness. It’s critical for Cairo’s provable computation.
Example:
cairo
assert x > 0;
14. What is the Cairo memory model?
Answer: Cairo uses a linear, immutable memory model where memory cells are written once. It operates with pointers (ap, fp) and supports temporary and persistent allocations.
15. How do you run a Cairo program locally?
Answer:
- Compile the program:
bash
cairo-compile program.cairo --output program.json
- Run with:
bash
cairo-run --program=program.json
Use –layout=small for Starknet-compatible execution.
Intermediate-Level Questions (16–35)
16. What is a Starknet syscall?
Answer: Syscalls are Starknet-specific functions that allow contracts to interact with the blockchain (e.g., read storage, emit events). Examples include get_caller_address and storage_write.
17. How do you define a Starknet contract in Cairo?
Answer: Use the @contract decorator and define storage, external functions, and events:
cairo
%lang starknet
@contract
mod MyContract {
@storage_var
func balance() -> (res: felt) {
}
@external
func increase_balance(amount: felt) -> () {
let (current) = balance.read();
balance.write(current + amount);
return ();
}
}
18. What is the @storage_var decorator?
Answer: @storage_var defines a storage variable in a Starknet contract, mapping to persistent blockchain storage. It generates read and write methods.
Example:
cairo
@storage_var
func counter() -> (res: felt) {
}
19. How do you call another contract in Starknet?
Answer: Use the @contract_interface to define the target contract’s interface and call it with invoke or call:
cairo
@contract_interface
namespace ITarget {
func increment() -> ();
}
func call_target(target: felt) -> () {
ITarget.increment(target);
return ();
}
20. What is the difference between @external and @view in Starknet?
Answer:
- @external: Marks functions that modify state and can be called externally.
- @view: Marks read-only functions that don’t modify state.
21. How do you handle errors in Cairo?
Answer: Use assert for critical checks or return custom error codes. For Starknet, use panic or revert with a message:
cairo
if (condition == 0) {
panic('Condition not met');
}
22. What is the pedersen hash function in Cairo?
Answer: The Pedersen hash is a cryptographic hash function used in Starknet for secure data commitments (e.g., storage keys, merkle trees). It’s implemented via the pedersen built-in.
Example:
cairo
from starkware.crypto.signature import pedersen_hash
let (hash) = pedersen_hash(a, b);
23. How do you deploy a Starknet contract using Cairo?
Answer:
- Compile the contract:
bash
starknet-compile contract.cairo --output contract.json
- Deploy using the Starknet CLI or a wallet (e.g., Argent X):
bash
starknet deploy --contract contract.json --network alpha-goerli
24. What is the implicit keyword in Cairo?
Answer: implicit declares variables that are automatically passed to functions (e.g., syscall_ptr, pedersen_ptr) to manage syscalls and cryptographic operations.
Example:
cairo
func my_func{syscall_ptr: felt*, pedersen_ptr: felt*}() -> () {
return ();
}
25. How do you write tests for a Cairo contract?
Answer: Use the pytest framework with the Starknet testing library:
- Write a test in Python:
python
from starkware.starknet.testing.starknet import Starknet
async def test_contract():
starknet = await Starknet.empty()
contract = await starknet.deploy("contract.cairo")
await contract.increase_balance(10).execute()
result = await contract.balance().call()
assert result.result == (10,)
- Run with pytest.
26. What is the role of the range_check built-in?
Answer: The range_check built-in ensures that values are within a specific range (e.g., non-negative or bounded), critical for secure arithmetic in STARK proofs.
27. How do you emit events in a Starknet contract?
Answer: Define an @event and emit it using emit_event:
cairo
@event
func ValueChanged(old: felt, new: felt) {
}
@external
func update{syscall_ptr: felt*}(value: felt) -> () {
ValueChanged.emit(old=0, new=value);
return ();
}
28. What is the cairo-lang package?
Answer: cairo-lang is the Python package providing Cairo’s compiler, runtime, and tools for compiling, running, and testing Cairo programs and Starknet contracts.
29. How do you handle arrays in Cairo?
Answer: Use alloc to create arrays and manage them with pointers:
cairo
let (arr: felt*) = alloc();
assert [arr] = 1; // Set first element
assert [arr + 1] = 2; // Set second element
30. What is the starknet-rs library?
Answer: starknet-rs is a Rust library for interacting with Starknet, used for building dApps, wallets, or tools that call Cairo contracts.
31. How do you optimize gas costs in Starknet contracts?
Answer:
- Minimize storage writes (most expensive).
- Use compact data structures (e.g., felt over structs).
- Batch operations to reduce syscalls.
- Avoid complex loops in mappings.
32. What is a STARK proof, and how does Cairo support it?
Answer: A STARK (Scalable Transparent Argument of Knowledge) proof verifies computation integrity off-chain. Cairo generates execution traces that the STARK prover converts into proofs, ensuring correctness and scalability.
33. How do you use invoke vs. call in Starknet?
Answer:
- invoke: Executes a state-changing function (e.g., @external).
- call: Reads data from a @view function without modifying state.
34. What is the starknet.js library?
Answer: starknet.js is a JavaScript library for interacting with Starknet contracts, enabling dApps to call Cairo functions, query storage, and manage transactions.
35. How do you handle contract upgrades in Starknet?
Answer: Use a proxy pattern:
- Deploy a proxy contract that delegates calls to an implementation contract.
- Update the implementation address in the proxy to upgrade.
- Ensure storage compatibility between versions.
Advanced-Level Questions (36–50)
36. What is the cairo-syscalls library?
Answer: The cairo-syscalls library provides low-level access to Starknet syscalls (e.g., get_block_number, storage_read), enabling contracts to interact with the blockchain environment.
37. How do you implement a factory contract in Cairo?
Answer: A factory contract deploys new contracts using deploy syscall:
cairo
@external
func deploy_contract{syscall_ptr: felt*}(class_hash: felt) -> (address: felt) {
let (address) = deploy(class_hash, contract_data);
return (address=address);
}
38. What is the class_hash in Starknet?
Answer: A class_hash is a unique identifier for a compiled Cairo contract’s bytecode. It’s used for deploying or referencing contract classes on Starknet.
39. How do you implement access control in a Starknet contract?
Answer: Use storage variables and modifiers to restrict access:
cairo
@storage_var
func owner() -> (res: felt) {
}
func only_owner{syscall_ptr: felt*}() -> () {
let (caller) = get_caller_address();
let (owner_addr) = owner.read();
assert caller = owner_addr;
return ();
}
40. What is the cairo-bootloader?
Answer: The cairo-bootloader is a tool for executing multiple Cairo programs in a single proof, used in Starknet for batching transactions to optimize proof generation.
41. How do you integrate Cairo contracts with Ethereum L1?
Answer: Use Starknet’s L1-L2 messaging bridge:
- Send messages from L1 to L2 via the Starknet core contract.
- Handle messages in Cairo using consume_message_from_l1.
- Send L2-to-L1 messages with send_message_to_l1.
42. What is the cairo-vm?
Answer: The cairo-vm (Cairo Virtual Machine) executes Cairo programs and generates execution traces for STARK proofs. It’s implemented in Rust and powers Starknet’s runtime.
43. How do you implement a Merkle tree in Cairo?
Answer: Use the Pedersen hash to build a Merkle tree:
cairo
func compute_merkle_root(leaves: felt*, len: felt) -> (root: felt) {
if (len == 1) {
return (root=leaves[0]);
}
let (left) = compute_merkle_root(leaves, len / 2);
let (right) = compute_merkle_root(leaves + len / 2, len / 2);
let (root) = pedersen_hash(left, right);
return (root=root);
}
44. How do you handle reentrancy in Starknet contracts?
Answer: Starknet’s sequential execution model prevents reentrancy by default. Still, use a non_reentrant modifier to ensure safety:
cairo
@storage_var
func locked() -> (res: felt) {
}
func non_reentrant{syscall_ptr: felt*}() -> () {
assert locked.read() = 0;
locked.write(1);
return ();
}
45. What is the starknet-foundry tool?
Answer: starknet-foundry is a Rust-based development framework for Cairo, providing tools for compiling, testing, and deploying Starknet contracts, similar to Hardhat for Ethereum.
46. How do you optimize proof generation in Cairo?
Answer:
- Minimize hint usage to reduce prover overhead.
- Use efficient algorithms (e.g., avoid nested loops).
- Leverage built-ins (e.g., pedersen, range_check).
- Batch syscalls to reduce trace size.
47. What is the account abstraction model in Starknet?
Answer: Starknet’s account abstraction treats accounts as contracts, allowing custom logic for transaction validation (e.g., multi-sig, session keys), implemented in Cairo.
48. How do you implement a governance contract in Cairo?
Answer:
- Define storage for proposals and votes.
- Use @external functions for proposing, voting, and executing.
- Implement access control and time locks:
cairo
@storage_var
func proposals(id: felt) -> (yes_votes: felt, no_votes: felt, deadline: felt) {
}
@external
func vote{proposal_id: felt, support: felt}() -> () {
// Voting logic
}
49. How do you debug a Cairo contract?
Answer:
- Use print statements in hints for runtime values.
- Test locally with starknet-devnet.
- Analyze execution traces with cairo-vm or starknet-foundry.
- Check Starknet’s transaction status on Voyager (block explorer).
50. How do you contribute to the Cairo ecosystem?
Answer:
- Write open-source Cairo contracts or libraries.
- Contribute to cairo-lang, starknet-rs, or starknet-foundry on GitHub.
- Create tutorials or subgraphs for Starknet data (e.g., using The Graph).
- Participate in Starknet’s developer hub or hackathons.