Learn Ethereum in 2024. #14. Accounts.
To discuss Ethereum accounts, let’s first recall the concept of the Ethereum state. Defining the Ethereum state precisely isn’t straightforward, but you can think of it as the collection of information regarding balances and code. In simpler terms, it encompasses details about ownership and the computational processes carried out by contracts.
The Ethereum state is stored in a data structure known as a modified Patricia Merkle trie. Although the name may sound complex, you can think of it simply as a map of key/value pairs. In such maps, based on a given key, we can store or retrieve the associated value. In Ethereum, each account address serves as a key, while the corresponding account information is the value stored in the trie.
You can think of an account address as the number of a safe deposit box, where information is stored. This address serves as a unique identifier for an account and is represented in hexadecimal format with 20 bytes, such as: 0x124892F22E1Db31C95abA7c32EAe00bD722cC19C.
There are two types of accounts on Ethereum: Externally Owned Accounts (EOAs) and contract accounts. Both are identified by addresses and contain associated information. One key distinction lies in control: EOAs are managed by individuals, while contract accounts are governed by their own code.
Externally Owned Accounts
EOAs function similarly to bank accounts, containing only two pieces of associated information: the account balance in ether and the nonce. Additional information, such as ownership of NFTs or tokens like DAI and USDC, are stored in the respective smart contracts for those assets. The account balance directly reflects the amount of the network’s native token, ether, associated with the account.
In EOAs, the nonce represents the number of transactions already executed by that account. The nonce serves to ensure that each transaction is unique. For instance, if account A sends 1 ether to account B and then sends another identical transaction shortly afterward, without the nonce, these transactions would be indistinguishable. By incorporating a unique number into each transaction, the nonce helps maintain the security of Ethereum.
Contract accounts
Contract accounts, in addition to a balance and a nonce, also have two other information fields. The first is the contract code. More precisely, what is recorded with the contract account is the hash of the contract. This design choice optimizes storage efficiency; if multiple contracts share the same code, the code itself only needs to be stored once. For now, the specific implementation details aren’t crucial; it’s important to understand that contracts have associated code.
The fourth and final piece of information associated with contract accounts is the contract’s storage. This storage acts as a private database for the contract, where it can store and retrieve data. For example, in the case of the DAI contract, information about how many DAIs each address owns is stored in its storage.
Transactions
Now, we have all the components required to comprehend the relationship between transactions and state. Ethereum operates as a transaction-based state machine, where state changes occur through transactions. The missing piece was that transactions are dispatched as messages signed by the EOAs.
An EOA consists of a pair of keys: public and private. The address is derived from the public key, specifically, the last 20 bytes of the keccak256 hash of the public key. Transactions are messages that must be signed by the private key. When an Ethereum node receives a transaction, its initial task is to authenticate the message and the message signature. Is the signature valid? Does the signature correspond to the address (the public key) that initiated the transaction? If not, the transaction is promptly rejected.
Keys and code
Therefore, creating an Ethereum account simply involves generating a pair of keys. Anyone can have an account, no questions asked. Moreover, individuals can possess an arbitrary number of accounts. However, to execute a transaction, a fee known as a gas fee, paid in ether, is required. This fee is necessary because without it, there would be no deterrent preventing individuals from inundating Ethereum with thousands of transactions. Given that network resources are limited, payment is required to utilize them.
Transactions can essentially perform two actions: transferring ether to another account and/or executing code in smart contracts. We will delve into this in detail in another article when we explore the structure of a transaction.
Contract accounts do not have associated keys and cannot send transactions. This is crucial to understand: only EOAs can send transactions. Contracts can execute functions in other contracts, but they never initiate a transaction. Contracts are passive agents. It is not possible to program a contract, for example, to act independently at a specific time.
Contracts also have an ether balance, enabling them to receive and send ether. However, as they are passive agents, they must be programmed to handle ether transactions. It’s quite common for poorly written contracts to receive ether without having functions to send that ether, resulting in the ether being locked up indefinitely.
Contracts also have a nonce. I mentioned earlier that the nonce represents the number of transactions sent by an account, but this is actually only true for EOAs. Contracts do not initiate transactions. Instead, in contract accounts, the nonce serves a different purpose: it indicates the number of contracts created by that contract. Contracts can create other contracts as well, as long as specified in their code.
How to create an account
Contract accounts are created by specific transactions, where the sender address is omitted, or by other contracts through transactions initiated by EOAs. In future articles, we will explore both methods of creating contract accounts.
You may wonder how the network knows which accounts have been created. It doesn’t. The network itself doesn’t create accounts or store private keys; that’s the responsibility of the users. Ethereum simply stores information from all accounts that have interacted with it. If a certain address has never interacted with the state, Ethereum won’t store information about it. However, once an address interacts with the state, that information is stored indefinitely.
Let’s see how this works. You can create a public and private key pair, as we did in a previous article. If you chose a truly random private key, you’ll have an address that’s uniquely yours. However, Ethereum doesn’t know about this yet; no node on the network is aware of it. You can create a transaction, sign it, and send it to the network. The signature will be valid, as you signed it with the correct private key. However, if you don’t have an ether balance to pay the gas fee, your transaction will be rejected.
One of the biggest challenges with blockchains is that to begin using the network, you need the network’s native token to pay gas fees. Typically, you acquire this native token from third parties, who then execute a transaction by sending the ether you purchased to the address you provided. From that moment on, the address exists in the state: it has a balance and a nonce, the latter initialized to zero.
It’s crucial to emphasize this point: when you create an account, whether through a programming language or a wallet like Metamask, the network isn’t informed. Unlike a bank, which requires Know Your Customer procedures, all Ethereum cares about is whether the transaction is valid and whether the account has the balance to cover the gas fee. Beyond that, it remains completely anonymous and doesn’t need any further information about account holders.