ethereum.shanghai.transactionsethereum.cancun.transactions

Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, transactions are the events that move between states.

TX_BASE_COST

Base cost of a transaction in gas units. This is the minimum amount of gas required to execute a transaction.

21
TX_BASE_COST = Uint(21000)

TX_DATA_COST_PER_NON_ZERO

Gas cost per non-zero byte in the transaction data.

27
TX_DATA_COST_PER_NON_ZERO = Uint(16)

TX_DATA_COST_PER_ZERO

Gas cost per zero byte in the transaction data.

32
TX_DATA_COST_PER_ZERO = Uint(4)

TX_CREATE_COST

Additional gas cost for creating a new contract.

37
TX_CREATE_COST = Uint(32000)

TX_ACCESS_LIST_ADDRESS_COST

Gas cost for including an address in the access list of a transaction.

42
TX_ACCESS_LIST_ADDRESS_COST = Uint(2400)

TX_ACCESS_LIST_STORAGE_KEY_COST

Gas cost for including a storage key in the access list of a transaction.

47
TX_ACCESS_LIST_STORAGE_KEY_COST = Uint(1900)

LegacyTransaction

Atomic operation performed on the block chain. This represents the original transaction format used before EIP-1559, and , EIP-2930, and EIP-4844.

53
@slotted_freezable
54
@dataclass
class LegacyTransaction:

nonce

66
    nonce: U256

gas_price

71
    gas_price: Uint

gas

76
    gas: Uint

to

81
    to: Union[Bytes0, Address]

value

87
    value: U256

data

92
    data: Bytes

v

98
    v: U256

r

103
    r: U256

s

108
    s: U256

Access

A mapping from account address to storage slots that are pre-warmed as part of a transaction.

114
@slotted_freezable
115
@dataclass
class Access:

account

122
    account: Address

slots

127
    slots: Tuple[Bytes32, ...]

AccessListTransaction

The transaction type added in EIP-2930 to support access lists.

This transaction type extends the legacy transaction with an access list and chain ID. The access list specifies which addresses and storage slots the transaction will access.

133
@slotted_freezable
134
@dataclass
class AccessListTransaction:

chain_id

146
    chain_id: U64

nonce

151
    nonce: U256

gas_price

156
    gas_price: Uint

gas

161
    gas: Uint

to

166
    to: Union[Bytes0, Address]

value

172
    value: U256

data

177
    data: Bytes

access_list

183
    access_list: Tuple[Access, ...]

y_parity

189
    y_parity: U256

r

194
    r: U256

s

199
    s: U256

FeeMarketTransaction

The transaction type added in EIP-1559.

This transaction type introduces a new fee market mechanism with two gas price parameters: max_priority_fee_per_gas and max_fee_per_gas.

205
@slotted_freezable
206
@dataclass
class FeeMarketTransaction:

chain_id

217
    chain_id: U64

nonce

222
    nonce: U256

max_priority_fee_per_gas

227
    max_priority_fee_per_gas: Uint

max_fee_per_gas

232
    max_fee_per_gas: Uint

gas

238
    gas: Uint

to

243
    to: Union[Bytes0, Address]

value

249
    value: U256

data

254
    data: Bytes

access_list

260
    access_list: Tuple[Access, ...]

y_parity

266
    y_parity: U256

r

271
    r: U256

s

276
    s: U256

BlobTransaction

The transaction type added in EIP-4844.

This transaction type extends the fee market transaction to support blob-carrying transactions.

282
@slotted_freezable
283
@dataclass
class BlobTransaction:

chain_id

294
    chain_id: U64

nonce

299
    nonce: U256

max_priority_fee_per_gas

304
    max_priority_fee_per_gas: Uint

max_fee_per_gas

309
    max_fee_per_gas: Uint

gas

315
    gas: Uint

to

320
    to: Address

value

326
    value: U256

data

331
    data: Bytes

access_list

337
    access_list: Tuple[Access, ...]

max_fee_per_blob_gas

343
    max_fee_per_blob_gas: U256

blob_versioned_hashes

348
    blob_versioned_hashes: Tuple[VersionedHash, ...]

y_parity

354
    y_parity: U256

r

359
    r: U256

s

364
    s: U256

Transaction

Union type representing any valid transaction type.

370
Transaction = Union[
281
    LegacyTransaction, AccessListTransaction, FeeMarketTransaction
371
    LegacyTransaction,
372
    AccessListTransaction,
373
    FeeMarketTransaction,
374
    BlobTransaction,
375
]

encode_transaction

Encode a transaction into its RLP or typed transaction format. Needed because non-legacy transactions aren't RLP.

Legacy transactions are returned as-is, while other transaction types are prefixed with their type identifier and RLP encoded.

def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]:
382
    """
383
    Encode a transaction into its RLP or typed transaction format.
384
    Needed because non-legacy transactions aren't RLP.
385
386
    Legacy transactions are returned as-is, while other transaction types
387
    are prefixed with their type identifier and RLP encoded.
388
    """
389
    if isinstance(tx, LegacyTransaction):
390
        return tx
391
    elif isinstance(tx, AccessListTransaction):
392
        return b"\x01" + rlp.encode(tx)
393
    elif isinstance(tx, FeeMarketTransaction):
394
        return b"\x02" + rlp.encode(tx)
302
    else:
303
        raise Exception(f"Unable to encode transaction of type {type(tx)}")
395
    elif isinstance(tx, BlobTransaction):
396
        return b"\x03" + rlp.encode(tx)
397
    else:
398
        raise Exception(f"Unable to encode transaction of type {type(tx)}")

decode_transaction

Decode a transaction from its RLP or typed transaction format. Needed because non-legacy transactions aren't RLP.

Legacy transactions are returned as-is, while other transaction types are decoded based on their type identifier prefix.

def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction:
402
    """
403
    Decode a transaction from its RLP or typed transaction format.
404
    Needed because non-legacy transactions aren't RLP.
405
406
    Legacy transactions are returned as-is, while other transaction types
407
    are decoded based on their type identifier prefix.
408
    """
409
    if isinstance(tx, Bytes):
410
        if tx[0] == 1:
411
            return rlp.decode_to(AccessListTransaction, tx[1:])
412
        elif tx[0] == 2:
413
            return rlp.decode_to(FeeMarketTransaction, tx[1:])
319
        else:
320
            raise TransactionTypeError(tx[0])
414
        elif tx[0] == 3:
415
            return rlp.decode_to(BlobTransaction, tx[1:])
416
        else:
417
            raise TransactionTypeError(tx[0])
418
    else:
419
        return tx

validate_transaction

Verifies a transaction.

The gas in a transaction gets used to pay for the intrinsic cost of operations, therefore if there is insufficient gas then it would not be possible to execute a transaction and it will be declared invalid.

Additionally, the nonce of a transaction must not equal or exceed the limit defined in EIP-2681. In practice, defining the limit as 2**64-1 has no impact because sending 2**64-1 transactions is improbable. It's not strictly impossible though, 2**64-1 transactions is the entire capacity of the Ethereum blockchain at 2022 gas limits for a little over 22 years.

Also, the code size of a contract creation transaction must be within limits of the protocol.

This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction after validation. It throws an InvalidTransaction exception if the transaction is invalid.

def validate_transaction(tx: Transaction) -> Uint:
423
    """
424
    Verifies a transaction.
425
426
    The gas in a transaction gets used to pay for the intrinsic cost of
427
    operations, therefore if there is insufficient gas then it would not
428
    be possible to execute a transaction and it will be declared invalid.
429
430
    Additionally, the nonce of a transaction must not equal or exceed the
431
    limit defined in [EIP-2681].
432
    In practice, defining the limit as ``2**64-1`` has no impact because
433
    sending ``2**64-1`` transactions is improbable. It's not strictly
434
    impossible though, ``2**64-1`` transactions is the entire capacity of the
435
    Ethereum blockchain at 2022 gas limits for a little over 22 years.
436
437
    Also, the code size of a contract creation transaction must be within
438
    limits of the protocol.
439
440
    This function takes a transaction as a parameter and returns the intrinsic
441
    gas cost of the transaction after validation. It throws an
442
    `InvalidTransaction` exception if the transaction is invalid.
443
444
    [EIP-2681]: https://eips.ethereum.org/EIPS/eip-2681
445
    """
446
    from .vm.interpreter import MAX_CODE_SIZE
447
448
    intrinsic_gas = calculate_intrinsic_cost(tx)
449
    if intrinsic_gas > tx.gas:
450
        raise InvalidTransaction("Insufficient gas")
451
    if U256(tx.nonce) >= U256(U64.MAX_VALUE):
452
        raise InvalidTransaction("Nonce too high")
453
    if tx.to == Bytes0(b"") and len(tx.data) > 2 * MAX_CODE_SIZE:
454
        raise InvalidTransaction("Code size too large")
455
456
    return intrinsic_gas

calculate_intrinsic_cost

Calculates the gas that is charged before execution is started.

The intrinsic cost of the transaction is charged before execution has begun. Functions/operations in the EVM cost money to execute so this intrinsic cost is for the operations that need to be paid for as part of the transaction. Data transfer, for example, is part of this intrinsic cost. It costs ether to send data over the wire and that ether is accounted for in the intrinsic cost calculated in this function. This intrinsic cost must be calculated and paid for before execution in order for all operations to be implemented.

The intrinsic cost includes:

  1. Base cost (TX_BASE_COST)

  2. Cost for data (zero and non-zero bytes)

  3. Cost for contract creation (if applicable)

  4. Cost for access list entries (if applicable)

This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction.

def calculate_intrinsic_cost(tx: Transaction) -> Uint:
460
    """
461
    Calculates the gas that is charged before execution is started.
462
463
    The intrinsic cost of the transaction is charged before execution has
464
    begun. Functions/operations in the EVM cost money to execute so this
465
    intrinsic cost is for the operations that need to be paid for as part of
466
    the transaction. Data transfer, for example, is part of this intrinsic
467
    cost. It costs ether to send data over the wire and that ether is
468
    accounted for in the intrinsic cost calculated in this function. This
469
    intrinsic cost must be calculated and paid for before execution in order
470
    for all operations to be implemented.
471
472
    The intrinsic cost includes:
473
    1. Base cost (`TX_BASE_COST`)
474
    2. Cost for data (zero and non-zero bytes)
475
    3. Cost for contract creation (if applicable)
476
    4. Cost for access list entries (if applicable)
477
478
    This function takes a transaction as a parameter and returns the intrinsic
479
    gas cost of the transaction.
480
    """
481
    from .vm.gas import init_code_cost
482
483
    data_cost = Uint(0)
484
485
    for byte in tx.data:
486
        if byte == 0:
487
            data_cost += TX_DATA_COST_PER_ZERO
488
        else:
489
            data_cost += TX_DATA_COST_PER_NON_ZERO
490
491
    if tx.to == Bytes0(b""):
492
        create_cost = TX_CREATE_COST + init_code_cost(ulen(tx.data))
493
    else:
494
        create_cost = Uint(0)
495
496
    access_list_cost = Uint(0)
400
    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
497
    if isinstance(
498
        tx, (AccessListTransaction, FeeMarketTransaction, BlobTransaction)
499
    ):
500
        for access in tx.access_list:
501
            access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
502
            access_list_cost += (
503
                ulen(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST
504
            )
505
506
    return TX_BASE_COST + data_cost + create_cost + access_list_cost

recover_sender

Extracts the sender address from a transaction.

The v, r, and s values are the three parts that make up the signature of a transaction. In order to recover the sender of a transaction the two components needed are the signature (v, r, and s) and the signing hash of the transaction. The sender's public key can be obtained with these two values and therefore the sender address can be retrieved.

This function takes chain_id and a transaction as parameters and returns the address of the sender of the transaction. It raises an InvalidSignatureError if the signature values (r, s, v) are invalid.

def recover_sender(chain_id: U64, ​​tx: Transaction) -> Address:
510
    """
511
    Extracts the sender address from a transaction.
512
513
    The v, r, and s values are the three parts that make up the signature
514
    of a transaction. In order to recover the sender of a transaction the two
515
    components needed are the signature (``v``, ``r``, and ``s``) and the
516
    signing hash of the transaction. The sender's public key can be obtained
517
    with these two values and therefore the sender address can be retrieved.
518
519
    This function takes chain_id and a transaction as parameters and returns
520
    the address of the sender of the transaction. It raises an
521
    `InvalidSignatureError` if the signature values (r, s, v) are invalid.
522
    """
523
    r, s = tx.r, tx.s
524
    if U256(0) >= r or r >= SECP256K1N:
525
        raise InvalidSignatureError("bad r")
526
    if U256(0) >= s or s > SECP256K1N // U256(2):
527
        raise InvalidSignatureError("bad s")
528
529
    if isinstance(tx, LegacyTransaction):
530
        v = tx.v
531
        if v == 27 or v == 28:
532
            public_key = secp256k1_recover(
533
                r, s, v - U256(27), signing_hash_pre155(tx)
534
            )
535
        else:
536
            chain_id_x2 = U256(chain_id) * U256(2)
537
            if v != U256(35) + chain_id_x2 and v != U256(36) + chain_id_x2:
538
                raise InvalidSignatureError("bad v")
539
            public_key = secp256k1_recover(
540
                r,
541
                s,
542
                v - U256(35) - chain_id_x2,
543
                signing_hash_155(tx, chain_id),
544
            )
545
    elif isinstance(tx, AccessListTransaction):
546
        if tx.y_parity not in (U256(0), U256(1)):
547
            raise InvalidSignatureError("bad y_parity")
548
        public_key = secp256k1_recover(
549
            r, s, tx.y_parity, signing_hash_2930(tx)
550
        )
551
    elif isinstance(tx, FeeMarketTransaction):
552
        if tx.y_parity not in (U256(0), U256(1)):
553
            raise InvalidSignatureError("bad y_parity")
554
        public_key = secp256k1_recover(
555
            r, s, tx.y_parity, signing_hash_1559(tx)
457
        )
556
        )
557
    elif isinstance(tx, BlobTransaction):
558
        if tx.y_parity not in (U256(0), U256(1)):
559
            raise InvalidSignatureError("bad y_parity")
560
        public_key = secp256k1_recover(
561
            r, s, tx.y_parity, signing_hash_4844(tx)
562
        )
563
564
    return Address(keccak256(public_key)[12:32])

signing_hash_pre155

Compute the hash of a transaction used in a legacy (pre EIP-155) signature.

This function takes a legacy transaction as a parameter and returns the signing hash of the transaction.

def signing_hash_pre155(tx: LegacyTransaction) -> Hash32:
568
    """
569
    Compute the hash of a transaction used in a legacy (pre [EIP-155])
570
    signature.
571
572
    This function takes a legacy transaction as a parameter and returns the
573
    signing hash of the transaction.
574
575
    [EIP-155]: https://eips.ethereum.org/EIPS/eip-155
576
    """
577
    return keccak256(
578
        rlp.encode(
579
            (
580
                tx.nonce,
581
                tx.gas_price,
582
                tx.gas,
583
                tx.to,
584
                tx.value,
585
                tx.data,
586
            )
587
        )
588
    )

signing_hash_155

Compute the hash of a transaction used in a EIP-155 signature.

This function takes a legacy transaction and a chain ID as parameters and returns the hash of the transaction used in an EIP-155 signature.

def signing_hash_155(tx: LegacyTransaction, ​​chain_id: U64) -> Hash32:
592
    """
593
    Compute the hash of a transaction used in a [EIP-155] signature.
594
595
    This function takes a legacy transaction and a chain ID as parameters
596
    and returns the hash of the transaction used in an [EIP-155] signature.
597
598
    [EIP-155]: https://eips.ethereum.org/EIPS/eip-155
599
    """
600
    return keccak256(
601
        rlp.encode(
602
            (
603
                tx.nonce,
604
                tx.gas_price,
605
                tx.gas,
606
                tx.to,
607
                tx.value,
608
                tx.data,
609
                chain_id,
610
                Uint(0),
611
                Uint(0),
612
            )
613
        )
614
    )

signing_hash_2930

Compute the hash of a transaction used in a EIP-2930 signature.

This function takes an access list transaction as a parameter and returns the hash of the transaction used in an EIP-2930 signature.

def signing_hash_2930(tx: AccessListTransaction) -> Hash32:
618
    """
619
    Compute the hash of a transaction used in a [EIP-2930] signature.
620
621
    This function takes an access list transaction as a parameter
622
    and returns the hash of the transaction used in an [EIP-2930] signature.
623
624
    [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930
625
    """
626
    return keccak256(
627
        b"\x01"
628
        + rlp.encode(
629
            (
630
                tx.chain_id,
631
                tx.nonce,
632
                tx.gas_price,
633
                tx.gas,
634
                tx.to,
635
                tx.value,
636
                tx.data,
637
                tx.access_list,
638
            )
639
        )
640
    )

signing_hash_1559

Compute the hash of a transaction used in an EIP-1559 signature.

This function takes a fee market transaction as a parameter and returns the hash of the transaction used in an EIP-1559 signature.

def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32:
644
    """
645
    Compute the hash of a transaction used in an [EIP-1559] signature.
646
647
    This function takes a fee market transaction as a parameter
648
    and returns the hash of the transaction used in an [EIP-1559] signature.
649
650
    [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
651
    """
652
    return keccak256(
653
        b"\x02"
654
        + rlp.encode(
655
            (
656
                tx.chain_id,
657
                tx.nonce,
658
                tx.max_priority_fee_per_gas,
659
                tx.max_fee_per_gas,
660
                tx.gas,
661
                tx.to,
662
                tx.value,
663
                tx.data,
664
                tx.access_list,
665
            )
666
        )
667
    )

signing_hash_4844

Compute the hash of a transaction used in an EIP-4844 signature.

This function takes a transaction as a parameter and returns the signing hash of the transaction used in an EIP-4844 signature.

def signing_hash_4844(tx: BlobTransaction) -> Hash32:
671
    """
672
    Compute the hash of a transaction used in an [EIP-4844] signature.
673
674
    This function takes a transaction as a parameter and returns the
675
    signing hash of the transaction used in an [EIP-4844] signature.
676
677
    [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844
678
    """
679
    return keccak256(
680
        b"\x03"
681
        + rlp.encode(
682
            (
683
                tx.chain_id,
684
                tx.nonce,
685
                tx.max_priority_fee_per_gas,
686
                tx.max_fee_per_gas,
687
                tx.gas,
688
                tx.to,
689
                tx.value,
690
                tx.data,
691
                tx.access_list,
692
                tx.max_fee_per_blob_gas,
693
                tx.blob_versioned_hashes,
694
            )
695
        )
696
    )

get_transaction_hash

Compute the hash of a transaction.

This function takes a transaction as a parameter and returns the keccak256 hash of the transaction. It can handle both legacy transactions and typed transactions (AccessListTransaction, FeeMarketTransaction, etc.).

def get_transaction_hash(tx: Union[Bytes, LegacyTransaction]) -> Hash32:
700
    """
701
    Compute the hash of a transaction.
702
703
    This function takes a transaction as a parameter and returns the
704
    keccak256 hash of the transaction. It can handle both legacy transactions
705
    and typed transactions (`AccessListTransaction`, `FeeMarketTransaction`,
706
    etc.).
707
    """
708
    assert isinstance(tx, (LegacyTransaction, Bytes))
709
    if isinstance(tx, LegacyTransaction):
710
        return keccak256(rlp.encode(tx))
711
    else:
712
        return keccak256(tx)