Understanding Ethereum Accounts: A Complete Guide to EOAs and Contract Accounts

·

Ethereum's account model is a foundational concept that powers its smart contract functionality and decentralized applications. Unlike Bitcoin’s UTXO (Unspent Transaction Output) system, Ethereum uses a more intuitive account-based model, making it easier to understand balances, transactions, and interactions with smart contracts. This structure enables Ethereum to function as a global, decentralized state machine — often described as a "world computer."

In this comprehensive guide, we’ll explore the two core types of Ethereum accounts: Externally Owned Accounts (EOAs) and Contract Accounts. We’ll dive into their data structures, differences, use cases, and how they interact within the Ethereum ecosystem.


What Are Ethereum Accounts?

At its core, Ethereum operates on an account-based ledger system where every user and smart contract has a unique account address. These accounts store balance information (in ETH), transaction history (via nonce), and — in the case of contracts — executable code and internal storage.

There are two primary types of accounts:

Both share the same underlying data structure but differ significantly in behavior and capabilities.

👉 Discover how Ethereum accounts power real-world blockchain applications today.


Externally Owned Accounts (EOAs)

An Externally Owned Account (EOA) is controlled by a private key and typically represents a human user or wallet. It serves as the main interface through which users interact with the Ethereum network.

Key Features of EOAs

Think of an EOA like a traditional bank account — you need credentials (your private key) to access and operate it. However, unlike banks, there's no central authority; control is entirely cryptographic.

EOAs are essential because only they can initiate transactions. Even if a smart contract wants to execute code, it must be triggered by an EOA.


Contract Accounts

A Contract Account is created when an EOA deploys a smart contract onto the blockchain. Once deployed, it exists at a specific address and contains:

How Contract Addresses Are Generated

When a contract is created, its address is deterministically derived using the creator’s address and transaction nonce:

Keccak256(rlp([sender, nonce]))[12:]

This ensures that contract addresses are unique and predictable before deployment.

Additionally, EIP-1014 introduced CREATE2, allowing contracts to be deployed to predictable addresses based on a salt value and initialization code:

keccak256(0xff ++ address ++ salt ++ keccak256(init_code))[12:]

This advancement supports advanced use cases like state channels and wallet recovery systems.

Key Capabilities of Contract Accounts

Unlike EOAs, contract accounts cannot act autonomously — they respond only when called.


EOA vs Contract Account: Key Differences

FeatureExternally Owned Account (EOA)Contract Account
Private Key Control✅ Yes❌ No
Balance✅ Yes✅ Yes
Executable Code❌ No✅ Yes
Can Initiate Transactions✅ Yes❌ Only responds to calls
Supports Multi-Signature Logic❌ Natively✅ Via smart contract design

While EOAs lack built-in features like multi-signature security, these can be implemented programmatically in contract accounts. For example, a wallet contract can require multiple approvals before releasing funds — something impossible with a basic EOA.


Ethereum Account Data Structure

All Ethereum accounts share the same internal structure defined in the protocol:

type Account struct {
    Nonce    uint64
    Balance  *big.Int
    Root     common.Hash
    CodeHash []byte
}

Let’s break down each field:

🔢 Nonce

The nonce is a counter that increments with every transaction sent from an EOA. For contract accounts, it tracks how many contracts the account has created.

It prevents replay attacks by ensuring each transaction is processed only once.

💰 Balance

The Balance field stores the account’s ETH holdings in wei, the smallest denomination of ether.

Transfers between accounts modify balances directly:

db.SubBalance(sender, amount)
db.AddBalance(recipient, amount)

Before any transfer, Ethereum checks if the sender has sufficient funds using CanTransfer.

🌲 State Root (Root)

The Root field points to the root hash of a Merkle Patricia Trie that stores all key-value pairs in a contract’s storage. Any change in contract state updates this root, enabling efficient verification of data integrity.

💾 Code Hash

The CodeHash contains the Keccak-256 hash of the account’s bytecode. For EOAs, this is always set to the hash of empty data (c5d2...). For contract accounts, it reflects the actual compiled smart contract code.

If CodeHash is not empty, the account is recognized as a contract.


Practical Example: Simulating Account Operations

Here’s a simplified Go example demonstrating how Ethereum manages accounts internally:

statadb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()))

acct1 := toAddr("0x0bB1...FF9a")
acct2 := toAddr("0x77de...51B")

statadb.AddBalance(acct1, big.NewInt(100))
statadb.AddBalance(acct2, big.NewInt(888))

contract := crypto.CreateAddress(acct1, statadb.GetNonce(acct1))
statadb.CreateAccount(contract)
statadb.SetCode(contract, []byte("contract code bytes"))

statadb.SetState(contract, toHash([]byte("owner")), toHash(acct1.Bytes()))
statadb.SetState(contract, toHash([]byte("name")), toHash([]byte("ysqi")))
statadb.Commit(true)

fmt.Println(string(statadb.Dump()))

After committing changes, Dump() outputs all account states in JSON format — showing balances, nonces, storage, and code for each account.

You can retrieve individual storage values using tools like web3.eth.getStorageAt, which queries specific storage slots in a contract.

👉 See how developers build secure wallets using Ethereum account logic.


Frequently Asked Questions (FAQ)

Q: Can a contract account own ETH?

Yes. Contract accounts can receive, hold, and send ETH just like EOAs. However, they can only do so when triggered by an external transaction or another contract call.

Q: How is an EOA different from a wallet?

An EOA is a cryptographic entity defined by a private key and address. A wallet is software or hardware that manages one or more EOAs, providing interfaces for signing transactions securely.

Q: Why does every account have a nonce?

The nonce prevents replay attacks by ensuring transactions are processed in order and only once. It also helps identify the next valid transaction from an account.

Q: Can I change a contract’s code after deployment?

No. Smart contracts are immutable by design. Once deployed, their code cannot be altered. Upgrades require deploying new contracts and migrating data.

Q: How are account addresses generated?

EOA addresses are derived from the public key using Keccak256, taking the last 20 bytes. Contract addresses are calculated from the creator’s address and nonce (or salt in CREATE2).

Q: Is it possible to lose funds in a contract?

Yes. If a contract has bugs or lacks withdrawal functions, funds may become permanently locked. Always audit contracts before sending value.


Core Keywords

👉 Start exploring Ethereum development with secure account management tools.