staticcall
STATICCALL is a message call that comes with a promise: the code it invokes is not allowed to change anything. It behaves like a normal CALL — it passes data, runs the target's code, returns a success flag and data — but the EVM enforces a read-only sandbox for the entire sub-execution, including any further calls it makes. It is the EVM's hardware-level guarantee that 'this is just a question, not an instruction'.
Introduced in EIP-214 (Byzantium, 2017), STATICCALL works by setting a 'static' mode flag on the new execution frame. While that flag is set, any opcode that would mutate state immediately reverts the call: SSTORE (storage writes), LOG0–LOG4 (emitting events), CREATE and CREATE2 (deploying contracts), SELFDESTRUCT, and any CALL that tries to forward non-zero ETH. Pure computation, SLOAD reads, and nested STATICCALLs are all fine. The flag propagates, so a contract cannot escape the restriction by calling out to a third contract.
This is exactly what Solidity uses to enforce view and pure functions when they are reached through an external call. When you call another contract's view function via an interface, the compiler emits a STATICCALL, giving you a compile-time and run-time guarantee that querying a price, a balance, or a configuration value cannot have surprising side effects on chain state.
The read-only guarantee makes STATICCALL a useful safety tool beyond just views. Calling untrusted code under STATICCALL means it cannot reenter and drain you or silently flip a flag, which is one reason oracle reads and certain cross-contract queries prefer it. The trade-off is rigidity: a function that needs to log an event or update a counter simply cannot be invoked through STATICCALL — the whole sub-call reverts the moment it tries.
A view function is not free of cost when called inside a transaction — STATICCALL still consumes gas for the computation and reads; 'free' only describes off-chain eth_call queries that never touch the mempool.