Track 3 · Ethereum & the EVM · lesson 2
Two kinds of account
6 min
Ethereum has exactly two kinds of account, and every address you will ever see is one of them.
| | Externally owned account | Contract account | |---|---|---| | Controlled by | a private key | its own code | | Has code | no | yes | | Can start a transaction | yes | no | | Created by | choosing a key | being deployed |
The asymmetry that matters: a contract can never act on its own.
It has no key, so it cannot sign. Every single thing a contract does begins with an externally owned account sending a transaction. There are no cron jobs, no timers, no background processes.
A contract that needs to do something "every day at noon" cannot. Somebody has to call it — which is why keeper networks and bots exist, and why they are paid.
Both share the same address space
You cannot tell from an address alone which kind it is. Both are 20 bytes, both hold ETH, both appear identically in a block explorer's URL.
The only way to tell is to look for code:
if (someAddress.code.length > 0) {
// it's a contract
}
That check is common — and, as you saw in the constructors lesson, defeatable from inside a constructor, where a contract has an address but no code yet.
Predict
A contract holds 500 ETH. Nobody has called it in a year. Can it send that ETH anywhere?
What an account actually stores
Both kinds hold four fields:
- nonce — for an EOA, how many transactions it has sent; for a contract, how many contracts it has created.
- balance — in wei.
- storageRoot — a fingerprint of its storage. Empty for an EOA.
- codeHash — a hash of its code. The hash of nothing, for an EOA.
An EOA is a contract account with the interesting parts empty.
Check
Which can initiate a transaction?
Worth remembering
- Two account types: externally owned (key-controlled) and contract (code-controlled).
- Only an EOA can start a transaction, because only a key can sign.
- Contracts are entirely reactive — every 'automatic' system has someone paid to call it.
- You cannot tell the types apart by address; you check whether code exists at it.
- Both store nonce, balance, storageRoot and codeHash — an EOA just leaves the last two empty.