EIP-1052: fingerprinting a contract in one opcode
To check whether another address runs exactly the bytecode you expect, you used to copy its entire code into memory and hash it yourself — an O(code-size) operation just to get a 32-byte fingerprint. EIP-1052 adds EXTCODEHASH, which returns that hash directly, in constant time.
- accounts & code (EXTCODECOPY)
- keccak256 hashing
Constantinople, February 2019. A contract often needs to know what another account is made of. Is this address a contract or a plain wallet? Is it running the exact bytecode I audited, or something I don’t recognize? The cleanest way to answer is with a fingerprint — a hash of the account’s code you can compare against a known value. The EVM could already hash things and could already read other accounts’ code, but it had no way to get that fingerprint cheaply: you had to haul the entire code into memory and hash it yourself. EIP-1052 adds the one opcode that skips the haul. Let’s derive it.
The problem: to hash the code, you first had to copy all of it
Before EIP-1052, the EVM’s tools for inspecting another account’s code were EXTCODESIZE Returns the length in bytes of the code at a given address. Useful, but a length isn't an identity — two different contracts can share a size. (its length) and EXTCODECOPY Copies a range of another account's code into the caller's memory. To fingerprint the code you had to copy all of it, then hash the copy — cost proportional to the code's size, plus memory-expansion gas. (its bytes). Neither gives you a fingerprint directly. So to obtain the keccak256 of a contract’s code — the thing you actually want for an identity check — you had to EXTCODECOPY the whole code into your own memory and then run KECCAK256 over it. The cost scales with the code’s size and pays memory-expansion gas on top, all to produce a single 32-byte value. For a large contract, that’s a lot of work for a comparison.
→ Step 2: expose the code hash as its own opcode.
EIP-1052: EXTCODEHASH returns the hash directly
The fix adds EXTCODEHASH Opcode 0x3f. Given an address, returns the keccak256 hash of that account's code in constant time — no copying. The node can serve it directly, since the code hash is part of an account's stored representation. (0x3f): give it an address, get back the keccak256 of that account’s code in a single, constant-time instruction — no copying, no memory expansion. But it comes with edges you must respect, all about the absence of code. A non-existent account An address that has never been touched — no balance, nonce, or code. EXTCODEHASH returns 0 for it, distinguishing 'nothing here' from 'here but codeless'. returns 0. An account that exists but has no code — a plain EOA, or a contract mid-construction — returns the empty-code hash keccak256 of the empty byte string (0xc5d2460186…), the code hash of any existing account with no deployed code. EXTCODEHASH returns this for EOAs, which is different from the 0 returned for non-existent accounts. , keccak256(""). Two distinct “no code” answers, and using the opcode correctly means telling them apart.
→ Step 3: what the cheap fingerprint unlocks.
The payoff: verifying what you’re talking to
A constant-time code hash makes a whole family of checks practical. A contract can confirm a counterparty is running exactly the known-safe bytecode it expects before trusting it. It can distinguish contracts from EOAs (with the empty-code and construction caveats in mind). And it pairs naturally with CREATE2: after deploying to a deterministic address, a contract can EXTCODEHASH it to confirm the deployed code is precisely what was intended — a real safety check for factories and upgrade patterns. What used to be an O(code-size) copy-and-hash is now one O(1) opcode, cheap enough to do inline on a hot path.