Solidity REPL
GUIDE8 min readMaintained by @Bitmay

Build a reproducible Solidity investigation

A useful investigation does more than produce a value. It records the question, the assumptions that led to the result, the exact Solidity that ran, and the effects that prove the conclusion. This guide builds that record from the first entry through review and handoff.

OUTCOMEA clean transcript that another person can rerun to verify the same Solidity conclusion.
  • Reduce an open-ended question to one observable claim
  • Build dependencies without hiding failures or state changes
  • Choose the evidence that proves the result
  • Preserve the compiler, context, source, and execution record
01

Define the claim before writing code

Begin with a sentence that can be proved by an observable result. “What does this contract do?” is too broad. “Does this fee calculation round down for 10 wei?” or “Which storage slot changes after set(42)?” gives the investigation a boundary and a success condition.

Choose the smallest first entry that establishes the input. Keep expected values, addresses, units, and compiler assumptions visible instead of burying them inside a large contract. This makes a wrong assumption easy to identify later.

uint256 amount = 10 wei
uint256 feeBps = 3333

amount * feeBps / 10_000
02

Build the dependency chain in visible steps

Add declarations, helper functions, types, imports, and contracts as separate logical steps. Every accepted entry joins the cumulative program, so later expressions can reuse earlier names. Small entries reveal which assumption introduced a change and keep each result next to the code that produced it.

Use a helper when the same operation appears more than once, then test the boundary cases that could change the conclusion. For arithmetic this may mean zero, a maximum value, or a rounding boundary. For a contract it may mean a second caller, an empty balance, or a repeated call.

function fee(uint256 amount, uint256 bps) pure returns (uint256) {
  return amount * bps / 10_000;
}

fee(amount, feeBps)
fee(0, feeBps)
fee(30_000, feeBps)
03

Use rejected attempts to locate the boundary

A rejected entry remains visible but does not join accepted history. The clean replay continues to represent the last program that compiled and executed successfully. That separation lets you try a suspected failure without silently changing the evidence underneath earlier results.

Read the error beside the rejected entry and decide whether it disproves the claim or exposes a bad input. Edit and rerun it when the corrected version belongs in the record. Editing or deleting an accepted entry revalidates the complete history before changing the working sequence.

04

Collect evidence that matches the claim

A typed inline value is enough for a pure calculation. A contract interaction usually needs more. Use Logs to prove which event and arguments were emitted, Calls to reconstruct external message flow, State to confirm committed storage writes, and Debug when source-level results do not explain the opcode path.

Match each conclusion to a visible observation. If the claim concerns a nested call, record its destination and output. If it concerns persistence, verify the final storage effect rather than relying only on the setter return value.

05

Freeze the record before sharing the conclusion

Review Replay source to see the cumulative Solidity document that was compiled. Confirm the compiler and execution context, including caller, value, chain, and fork block when they affect the answer. Changing any of these inputs can change the result.

Export the session when the investigation must be reviewed or resumed. The export preserves code, entries, files, compiler settings, and reproducible context while excluding the RPC URL. State the conclusion in terms of the collected evidence and include the block number for fork work.

FAQ

Common questions

What makes a Solidity investigation reproducible?

It records the accepted code, generated replay source, compiler, execution context, local files, and a fixed chain block when a fork is involved. Another person should be able to rerun those inputs and inspect the same evidence.

Does a failed entry change earlier results?

No. A failed attempt stays visible for correction, while the active replay remains on the last fully accepted history.

When should I use Source mode instead?

Use Source mode when the complete file is the main object you are editing or when an experiment intentionally needs persistent EVM state between runs. Use the REPL when the sequence of questions and answers is the evidence.