Day-Of Tactics
Read this the morning of. Structural moves that hold up across math rounds, live coding, code review, and behavioral. The advice that helps in the last 30 minutes before you log in.
Pre-loop
- Sleep. Single biggest predictor of performance. Caffeine doesn't substitute.
- Skim 04 and 05. The AMM math and gas chapters. Refresh, don't memorize.
- Re-derive
getAmountOutfromx · y = kon paper. If the derivation feels slow, do it twice. - Skim 08. The bug catalog. The 10 categories should feel automatic.
- Drill 5 questions from 15 out loud. Hearing your own voice on these topics anchors you.
- Set up your environment. Foundry installed, VSCode open, scratch contract ready. If they share a CodeSandbox or Remix, log in early.
- Glass of water, paper, pen. You will derive on paper. Don't fight a touchpad.
Structural moves for AMM math rounds
The math round wants to see reasoning, not memorization. The structural sequence:
- State the invariant out loud. "I'll work with
x · y = khere." If the question is v3, "I'll use the virtual-reserves form(x + L/√P_b)(y + L·√P_a) = L²." - Derive the formula. Don't recite. Show the substitution.
- Check edge cases at boundaries. "At
P = P_a, position is all token0. AtP = P_b, all token1. The formula collapses correctly." - Mention rounding direction. "I round down on output / up on input — always in protocol favor."
- Flag the production gotchas. Fee-on-transfer, decimals, fixed-point precision, FullMath.mulDiv if values can overflow.
- Sketch the test. "I'd fuzz this against a Python reference; invariant-test for K monotonicity."
If you draw a blank on a derivation, narrate it: "I'll start from the invariant. x · y = k. After a swap of Δx in, the new reserves are (x + Δx) and (y − Δy). The fee deducts (1−f) from the input…" Talking yourself through the algebra is how you avoid freezing.
Live Solidity coding round
Common round shapes:
- Implement X from scratch. 30-45 min. Usually a small contract: minimal AMM, ERC-4626 vault, simple staking.
- Add a feature to a given codebase. The given code is intentionally rough — fix the bugs first.
- Optimize this function. Show the 5-10 standard moves from chapter 05.
- Find the bug. They show you a function. Spot what's wrong.
The structural moves
- Restate the problem. "Just to make sure: you want a function that takes (a, b, c) and returns (d, e), with invariant Q."
- Clarify edge cases up front. "What if amountIn is zero? What if reserves are zero? Should this revert or no-op?"
- State the invariant before code. "I'll maintain that post-swap reserves satisfy
r0' * r1' >= r0 * r1." - Stub the function. Type signature, modifier, return statement. Compiles before any logic.
- Validate inputs. Custom errors.
if (amountIn == 0) revert ZeroIn(); - Cache storage reads.
(uint256 r0, uint256 r1) = (reserve0, reserve1); - Implement the math. Comment the rounding direction.
- Update state. Then emit event. Then external call.
- Mention what you'd test. Two unit tests, one invariant.
- If time: optimize. Walk through your standard list aloud.
If you get stuck, narrate the stuck. "I'm trying to figure out whether to use mulDiv here. The intermediate is at most 2^160 * 2^128 which overflows 256 bits — yes, mulDiv." This is faster than silent thinking and it shows your work.
Code-review round
They show you 50-200 lines and ask you to review it. The reviewer round tests your bug-catching reflexes more than your coding speed.
Standard sweep
- Read the contract end-to-end once, no comments. Get the shape.
- List the trust assumptions. Who can call what? Where are external calls?
- Walk the bug catalog from chapter 08. Fee-on-transfer? Reentrancy? Bad math at boundaries? Approval issues? Selector clash? Storage collision? Read-only reentrancy?
- Check rounding directions. Every division.
- Check storage layout. Packed correctly? Hot reads in one slot?
- Check event coverage. Every state change emits.
- Check input validation. Zero checks, deadline checks, slippage protection.
- Check the "and then" failure modes. What happens if the external call reverts? If the callback caller is malicious?
End with: "If I had more time, I'd want to fuzz this for [specific property] and check the storage layout against the upgrade history."
Behavioral
Common questions and the senior-grade frame:
"Tell me about your hardest production mistake."
Pick a real one. Be specific. Name the bug class (decimal mismatch, fee-on-transfer assumption, rounding bug). Walk through detection, response, lasting fix to your process. The interviewer is checking for ownership and the durability of the lesson. Don't make it about "we shipped a small typo." Make it about a real category of bug you now catch.
"Tell me about a gas optimization you're proud of."
Pick something with measurable before/after. "We were spending ~145k gas per swap; profiling showed three SLOADs we didn't need. Packed slot0, added immutables for the fee tier, switched to FullMath.mulDiv instead of unchecked multiply — landed at 108k. Verified with forge snapshot." Numbers matter here.
"Tell me about your relationship with audit firms."
Cite specific firms you've worked with. Describe what you do before kickoff (docs, threat model, tests). Describe how you handle findings (no arguing, fast turn-arounds, public publication after). End with a small process improvement you've adopted from an auditor.
"Why are you interested in this role specifically?"
Be honest. Connect to the design space — concentrated liquidity, hooks, intent-based architecture, multi-billion-TVL discipline. Avoid generic "love DeFi" framings. Senior interviewers can tell.
Questions to ask them
You will be asked. Have 5 ready. Tier them by interviewer role:
For an engineer interviewer
- "What's the biggest unfixed bug in the codebase, in your opinion?"
- "How does the team decide what goes into core vs periphery?"
- "What's the test pyramid look like? How much do you rely on Foundry invariant vs Echidna vs Halmos?"
- "Walk me through your most recent mainnet deployment. What surprised you?"
- "What's the on-call rotation like?"
For an engineering manager
- "How do you measure senior engineer impact at this team?"
- "What's the split between research-driven projects and product-driven ones?"
- "What's the path for an engineer who wants to lead a new mechanism design?"
For a hiring manager / leadership
- "What's the team's belief about immutability vs upgradeability for new core releases?"
- "How do you think about the next 18 months for this protocol?"
- "What's the failure mode you worry most about?"
Closing
- End strong. The last 5 minutes of the loop linger. Get a question in. Smile.
- Thank them. One sentence. Don't perform gratitude.
- Note one concrete thing from the conversation that landed for you. Names what you found compelling — signals fit.
- Ask about timeline. "What's the next step on your end?"
- Send a short follow-up within 24h to your recruiter or main contact. One paragraph. Specific.
Anti-patterns to avoid
- Bluffing about v3 or v4. "I've used v3" ≠ "I've read UniswapV3Pool.sol." Senior interviewers can tell in 30 seconds.
- Reciting without deriving. Memorized formulas evaporate under follow-up. Show the substitution.
- Premature gas optimization. Correctness first. Always. Don't reach for
uncheckedin a function you haven't proven works. - Skipping the invariant. Any design answer that doesn't open with the invariant is a yellow flag.
- Treating fee-on-transfer / decimals / non-standard ERC-20 as edge cases. They are the common case in production.
- Talking past the question. If they ask about hooks, answer about hooks — not what you'd rather discuss.
- Defensiveness in code review. When they push back, "you're right, let me re-examine" beats "but actually."
You are being hired to be the engineer auditors trust to defend the bytecode. Every answer should feel like it comes from someone who has held that responsibility — or who clearly will, soon.