Docs / Application security

Field guide · Smart contract security

Smart contract security

How an Ethereum transaction really works

By Abhimanyu Gupta, Founder & Principal Operator

On this page

Almost every on-chain attack is an ordinary transaction. Learn the fields, what gas really meters, why the mempool is public, and what the nonce does, and most smart contract security reads more clearly.

Read with a purpose. The sender is recovered from the signature, gas caps your downside and flags denial-of-service risk, the mempool previews your action to everyone, and the nonce orders transactions but never off-chain signatures.

At a glance

What a transaction is
A signed instruction to the network: move value, or run a contract function, from one account and pay for the computation
What gas is
The meter. Every operation costs gas, you pay for what you use, and you set a ceiling so a runaway call cannot drain your wallet
The public part
Before a transaction is mined it sits in the mempool, visible to everyone. That preview is the root of front-running
The nonce
A per-account counter that fixes the order of your transactions and stops the same one from being mined twice
Why it matters for security
Most on-chain attacks are ordinary transactions. Knowing the fields tells you what an attacker can see, reorder and pay to jump ahead of

The anatomy of a transaction

Everything that ever changes on Ethereum happens because someone sent a transaction. A transaction is a small, signed message with a fixed set of fields. Read them once and the rest of this section, and much of smart contract security, becomes easier to follow.

A transaction, field by fieldsolidity
{
  "to":       "0x1f98...F984",   // recipient: a wallet or a contract
  "value":    "1000000000000000000",  // 1 ETH, in wei
  "data":     "0xa9059cbb...",   // which function to call, and its arguments
  "nonce":    7,                 // this sender's 8th transaction (counts from 0)
  "gasLimit": 21000,             // the most gas you will allow it to burn
  "maxFeePerGas": "30000000000", // the most you will pay per unit of gas
  "maxPriorityFeePerGas": "1500000000"  // the tip to the validator
  // no "from" field: the sender is recovered from the signature
}

The detail worth pausing on is the last one. There is no from field. The sender is not stated; it is recovered from the signature by the network. Sign a message and the maths reveals exactly one address that could have produced that signature, and that address is you. This is why a leaked private key is total: anyone holding it can produce your signature, and the chain cannot tell the difference.

Gas, and why it exists

Ethereum runs every transaction on thousands of machines at once, so unbounded computation would be a denial-of-service weapon: one infinite loop could freeze the network. Gas is the defence. Each low-level operation has a fixed gas cost, the transaction carries a gasLimit, and execution halts the moment it runs out. You pay for the work done either way, but a limit means a mistake costs you a bounded fee rather than your whole balance.

The price has two parts. The base fee is set by the network and burned; it rises when blocks are full and falls when they are empty. The priority fee, or tip, goes to the validator and is how you ask to be included sooner. You set a maxFeePerGas as your ceiling, and anything between the base fee and your ceiling that you did not need is refunded. The headline number people quote, in gwei (a billionth of an ether), is just gas used multiplied by the price per gas.

Gas is a security signal, not just a cost. A function that loops over an array an attacker can grow can be pushed past the block gas limit, so it can never complete: a denial of service written in your own code. When you review a contract, every unbounded loop and every externally controlled array length is a place to ask "what is the most gas this can consume, and who decides?"

The mempool is public

When you broadcast a transaction it does not go straight into a block. It waits in the mempool, the pending pool that every node shares. For those few seconds your intended action is public: the function you are about to call, the amount, the price you are paying to be included. Only after a validator picks it up and builds a block does it become final.

That waiting room is the reason a whole class of attacks exists. Anyone can watch the mempool, see a profitable transaction before it lands, and pay a higher tip to have their own transaction ordered in front of it. The chain does not promise first-come-first-served; it largely sells ordering to the highest bidder. We treat that as its own subject in the guide on front-running and value extraction.

Walletsigns Mempoolpublic, pending Validatororders and builds Blockfinal anyone can read it here, before it is mined

The nonce: order and replay protection

Each account has a nonce, a counter that starts at zero and rises by one with every transaction it sends. It does two quiet but important jobs. It fixes order: the network will not process transaction 8 before transaction 7, so your actions apply in the sequence you signed them. And it stops replay: once transaction 7 is mined, no transaction with nonce 7 from your account can ever be mined again, so a signed transaction someone copied cannot be resubmitted for a second effect.

Keep that idea in mind, because it has a sharp edge. The nonce protects transactions. It does nothing for off-chain signatures, the messages you sign that a contract accepts later. Those have no built-in counter, so a contract that accepts signed messages has to add its own, and the ones that forget are the subject of the signature replay guide.

The short version. A transaction is a signed instruction with no sender field; the sender is recovered from the signature, which is why the key is everything. Gas meters the work, caps your downside, and quietly flags denial-of-service risk in unbounded loops. Between broadcast and inclusion the transaction sits in a public mempool, which is why ordering can be bought. And the account nonce orders your transactions and blocks replay, but only for transactions, never for the off-chain signatures a contract verifies itself.

References & further reading

  1. Ethereum community, Transactions. The fields of a transaction and how the sender is recovered from the signature.
  2. Ethereum community, Gas and fees. Base fee, priority fee, and the EIP-1559 market.
  3. Ethereum community, Accounts. Where the nonce lives and what it guarantees.
  4. Ethereum community, Maximal extractable value (MEV). Why the public mempool turns ordering into a market.
All guides Web app penetration testing

Want this tested on you?

Reading about it is one thing. Seeing it proven on your own systems is another.