Library
Mastering Ethereum: Building Smart Contracts and DApps · 13 of 15
Mastering Ethereum: Building Smart Contracts and DApps
blockchain HIGH

Transactions — Ethereum's Sole Canonical State-Change Input

transactions rlp nonce gas ecdsa replay-protection eip-155

Key Principle

A transaction is an RLP-encoded binary message signed by an EOA, and it is the only input that drives the EVM to change Ethereum's state. "The network-serialization is the only standard form of a transaction" (Chapter 6) — everything else (a UI "from" field, block number, transaction ID) is derived metadata added by tooling, not authoritative. The seven RLP fields are: nonce, gasPrice, gasLimit, to (recipient), value, data, and v,r,s (the ECDSA signature). RLP fields carry no labels or delimiters; the length prefix bounds each field, "anything beyond the defined length belongs to the next field" (Chapter 6).

Why This Matters

There is no "from" field. Identity is tied cryptographically to the signature, not asserted — "The EOA's public key can be derived from the v,r,s components of the ECDSA signature. The address can, in turn, be derived from the public key" (Chapter 6). Treating tooling-added metadata as part of the signed transaction produces bugs about what was actually authorized. Because the recorded transaction is irreversible — "it is not possible to 'recall' a transaction!" (Chapter 6) — every field error (wrong recipient, mis-encoded chain ID, gap in the nonce) is unrecoverable.

Good Examples

  • Nonce semantics (ordering + replay protection). The nonce is "A sequence number, issued by the originating EOA, used to prevent message replay" (Chapter 6). It is zero-based, an attribute of the originating address, and not stored in account state — "calculated dynamically, by counting the number of confirmed transactions that have originated from an address." It substitutes for Bitcoin's UTXO model: a higher-nonce tx "will be ignored until the transactions with nonces from 0 to 3 have been processed, even if it is received first," and the incrementing nonce makes each tx unique so "it is simply not possible for anyone to 'duplicate' a payment you have made" (Chapter 6).
  • Gas fields. gasPrice is wei paid per gas unit; gasLimit is "the maximum number of units of gas the transaction originator is willing to buy" (Chapter 6). An EOA-to-EOA transfer is fixed at 21,000 gas. Billing is credit-account, not prepaid: validation checks the sender can cover gasPrice * gasLimit up front "but the amount is not actually deducted… until the transaction finishes executing. You are only billed for gas actually consumed." [DATED 2018: EIP-1559 (2021) replaced single gasPrice with base fee + maxPriorityFeePerGas tip and maxFeePerGas cap.]
  • Contract creation via the zero address. Set to = 0x0 and put compiled bytecode in data. The deployed address is not in to (which is null) — it appears in the receipt's contractAddress (Chapter 6):
    > web3.eth.sendTransaction({from: src, to: 0, data: faucet_code, gas: 113558, gasPrice: 200000000000});
    // receipt: contractAddress: "0xb226...cf40b", to: null, status: "0x1"
  • ECDSA signing over the hash. "When we say 'sign the transaction' we actually mean 'sign the Keccak-256 hash of the RLP-serialized transaction data'" (Chapter 6). Flip any field and the hash changes, invalidating the signature — the tamper-evidence property the EOA model depends on.

Counterpoints

  • Unvalidated recipient burns ether. "Ethereum does no further validation of this field. Any 20-byte value is considered valid" (Chapter 6). A wrong to "will probably burn the ether sent, rendering it forever inaccessible" — no private key exists to sign a spend. Validation must live at the UI layer (EIP-55 checksum), never the protocol. Intentional burns should use 0x000000000000000000000000000000000000dEaD, not 0x0.
  • No EIP-155 chain ID = replay. Without the chain ID folded into the signed hash, "a tx valid on mainnet could be re-broadcast and executed on Ethereum Classic / a testnet (replay), draining funds." EIP-155 adds three fields (chainID, 0, 0) before hashing; "the signature is invalidated if the chain identifier is modified" (Chapter 6). Activated at block #2,675,000 (Spurious Dragon).
  • getTransactionCount is unreliable for pending. Under rapid-fire sends, getTransactionCount(address, "pending") undercounts — "it cannot rely on getTransactionCount for pending transactions" (Chapter 6). Track the nonce locally until each confirms. A nonce gap leaves higher-nonce txs stuck in the mempool and cannot be safely abandoned (no recall).
  • Multisig is application-layer, not protocol. "Ethereum's basic EOA value transactions have no provisions for multiple signatures" (Chapter 6). M-of-N is a wallet contract; "it is a double-edged sword, as the extra flexibility can lead to bugs that undermine the security of multisignature schemes" — this is the Parity multisig bug class.

Key Quotes

"When we say 'sign the transaction' we actually mean 'sign the Keccak-256 hash of the RLP-serialized transaction data.'" — Antonopoulos & Wood, Chapter 6 "Ethereum does no further validation of this field. Any 20-byte value is considered valid." — Antonopoulos & Wood, Chapter 6 "By including the chain identifier in the data being signed, the transaction signature prevents any changes, as the signature is invalidated if the chain identifier is modified." — Antonopoulos & Wood, Chapter 6

Rules of Thumb

  • Never trust a "from" field — the sender is recovered from v,r,s, so verify against the signature.
  • Always set to explicitly with gasPrice/gasLimit; accidentally targeting 0x0 burns ether unrecoverably.
  • Over-provision gasLimit for contract calls (gas "can be estimated but cannot be determined with accuracy"); 21,000 is exact only for EOA transfers.
  • Track nonces locally under concurrency; never assume getTransactionCount("pending") is current.
  • Sign offline / air-gapped: only the build step needs current nonce + funds online; isolate the keys for signing — "even a small degree of isolation has significant security benefits" (Chapter 6).
  • Validate recipients (EIP-55) at the UI layer — the protocol will not.

Related References

Diagram

Diagram