ethereum.forks.shanghai.transactionsethereum.forks.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.

GAS_TX_BASE

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

27
GAS_TX_BASE = Uint(21000)

GAS_TX_DATA_PER_NON_ZERO

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

33
GAS_TX_DATA_PER_NON_ZERO = Uint(16)

GAS_TX_DATA_PER_ZERO

Gas cost per zero byte in the transaction data.

38
GAS_TX_DATA_PER_ZERO = Uint(4)

GAS_TX_CREATE

Additional gas cost for creating a new contract.

43
GAS_TX_CREATE = Uint(32000)

GAS_TX_ACCESS_LIST_ADDRESS

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

48
GAS_TX_ACCESS_LIST_ADDRESS = Uint(2400)

GAS_TX_ACCESS_LIST_STORAGE_KEY

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

53
GAS_TX_ACCESS_LIST_STORAGE_KEY = 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.

59
@slotted_freezable
60
@dataclass
class LegacyTransaction:

nonce

A scalar value equal to the number of transactions sent by the sender.

72
    nonce: U256

gas_price

The price of gas for this transaction, in wei.

77
    gas_price: Uint

gas

The maximum amount of gas that can be used by this transaction.

82
    gas: Uint

to

The address of the recipient. If empty, the transaction is a contract creation.

87
    to: Bytes0 | Address

value

The amount of ether (in wei) to send with this transaction.

93
    value: U256

data

The data payload of the transaction, which can be used to call functions on contracts or to create new contracts.

98
    data: Bytes

v

The recovery id of the signature.

104
    v: U256

r

The first part of the signature.

109
    r: U256

s

The second part of the signature.

114
    s: U256

Access

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

120
@slotted_freezable
121
@dataclass
class Access:

account

The address of the account that is accessed.

128
    account: Address

slots

A tuple of storage slots that are accessed in the account.

133
    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.

139
@slotted_freezable
140
@dataclass
class AccessListTransaction:

chain_id

The ID of the chain on which this transaction is executed.

152
    chain_id: U64

nonce

A scalar value equal to the number of transactions sent by the sender.

157
    nonce: U256

gas_price

The price of gas for this transaction.

162
    gas_price: Uint

gas

The maximum amount of gas that can be used by this transaction.

167
    gas: Uint

to

The address of the recipient. If empty, the transaction is a contract creation.

172
    to: Bytes0 | Address

value

The amount of ether (in wei) to send with this transaction.

178
    value: U256

data

The data payload of the transaction, which can be used to call functions on contracts or to create new contracts.

183
    data: Bytes

access_list

A tuple of Access objects that specify which addresses and storage slots are accessed in the transaction.

189
    access_list: Tuple[Access, ...]

y_parity

The recovery id of the signature.

195
    y_parity: U256

r

The first part of the signature.

200
    r: U256

s

The second part of the signature.

205
    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.

211
@slotted_freezable
212
@dataclass
class FeeMarketTransaction:

chain_id

The ID of the chain on which this transaction is executed.

223
    chain_id: U64

nonce

A scalar value equal to the number of transactions sent by the sender.

228
    nonce: U256

max_priority_fee_per_gas

The maximum priority fee per gas that the sender is willing to pay.

233
    max_priority_fee_per_gas: Uint

max_fee_per_gas

The maximum fee per gas that the sender is willing to pay, including the base fee and priority fee.

238
    max_fee_per_gas: Uint

gas

The maximum amount of gas that can be used by this transaction.

244
    gas: Uint

to

The address of the recipient. If empty, the transaction is a contract creation.

249
    to: Bytes0 | Address

value

The amount of ether (in wei) to send with this transaction.

255
    value: U256

data

The data payload of the transaction, which can be used to call functions on contracts or to create new contracts.

260
    data: Bytes

access_list

A tuple of Access objects that specify which addresses and storage slots are accessed in the transaction.

266
    access_list: Tuple[Access, ...]

y_parity

The recovery id of the signature.

272
    y_parity: U256

r

The first part of the signature.

277
    r: U256

s

The second part of the signature.

282
    s: U256

BlobTransaction

The transaction type added in EIP-4844.

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

288
@slotted_freezable
289
@dataclass
class BlobTransaction:

chain_id

The ID of the chain on which this transaction is executed.

300
    chain_id: U64

nonce

A scalar value equal to the number of transactions sent by the sender.

305
    nonce: U256

max_priority_fee_per_gas

The maximum priority fee per gas that the sender is willing to pay.

310
    max_priority_fee_per_gas: Uint

max_fee_per_gas

The maximum fee per gas that the sender is willing to pay, including the base fee and priority fee.

315
    max_fee_per_gas: Uint

gas

The maximum amount of gas that can be used by this transaction.

321
    gas: Uint

to

The address of the recipient. If empty, the transaction is a contract creation.

326
    to: Address

value

The amount of ether (in wei) to send with this transaction.

332
    value: U256

data

The data payload of the transaction, which can be used to call functions on contracts or to create new contracts.

337
    data: Bytes

access_list

A tuple of Access objects that specify which addresses and storage slots are accessed in the transaction.

343
    access_list: Tuple[Access, ...]

max_fee_per_blob_gas

The maximum fee per blob gas that the sender is willing to pay.

349
    max_fee_per_blob_gas: U256

blob_versioned_hashes

A tuple of objects that represent the versioned hashes of the blobs included in the transaction.

354
    blob_versioned_hashes: Tuple[VersionedHash, ...]

y_parity

The recovery id of the signature.

360
    y_parity: U256

r

The first part of the signature.

365
    r: U256

s

The second part of the signature.

370
    s: U256

Transaction

Union type representing any valid transaction type.

285
Transaction = LegacyTransaction | AccessListTransaction | FeeMarketTransaction
376
Transaction = (
377
    LegacyTransaction
378
    | AccessListTransaction
379
    | FeeMarketTransaction
380
    | BlobTransaction
381
)

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) -> LegacyTransaction | Bytes:
388
    """
389
    Encode a transaction into its RLP or typed transaction format.
390
    Needed because non-legacy transactions aren't RLP.
391
392
    Legacy transactions are returned as-is, while other transaction types
393
    are prefixed with their type identifier and RLP encoded.
394
    """
395
    if isinstance(tx, LegacyTransaction):
396
        return tx
397
    elif isinstance(tx, AccessListTransaction):
398
        return b"\x01" + rlp.encode(tx)
399
    elif isinstance(tx, FeeMarketTransaction):
400
        return b"\x02" + rlp.encode(tx)
305
    else:
306
        raise Exception(f"Unable to encode transaction of type {type(tx)}")
401
    elif isinstance(tx, BlobTransaction):
402
        return b"\x03" + rlp.encode(tx)
403
    else:
404
        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: LegacyTransaction | Bytes) -> Transaction:
408
    """
409
    Decode a transaction from its RLP or typed transaction format.
410
    Needed because non-legacy transactions aren't RLP.
411
412
    Legacy transactions are returned as-is, while other transaction types
413
    are decoded based on their type identifier prefix.
414
    """
415
    if isinstance(tx, Bytes):
416
        if tx[0] == 1:
417
            return rlp.decode_to(AccessListTransaction, tx[1:])
418
        elif tx[0] == 2:
419
            return rlp.decode_to(FeeMarketTransaction, tx[1:])
322
        else:
323
            raise TransactionTypeError(tx[0])
420
        elif tx[0] == 3:
421
            return rlp.decode_to(BlobTransaction, tx[1:])
422
        else:
423
            raise TransactionTypeError(tx[0])
424
    else:
425
        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 InsufficientTransactionGasError exception if the transaction does not provide enough gas to cover the intrinsic cost, and a NonceOverflowError exception if the nonce is greater than 2**64 - 2. It also raises an InitCodeTooLargeError if the code size of a contract creation transaction exceeds the maximum allowed size.

def validate_transaction(tx: Transaction) -> Uint:
429
    """
430
    Verifies a transaction.
431
432
    The gas in a transaction gets used to pay for the intrinsic cost of
433
    operations, therefore if there is insufficient gas then it would not
434
    be possible to execute a transaction and it will be declared invalid.
435
436
    Additionally, the nonce of a transaction must not equal or exceed the
437
    limit defined in [EIP-2681].
438
    In practice, defining the limit as ``2**64-1`` has no impact because
439
    sending ``2**64-1`` transactions is improbable. It's not strictly
440
    impossible though, ``2**64-1`` transactions is the entire capacity of the
441
    Ethereum blockchain at 2022 gas limits for a little over 22 years.
442
443
    Also, the code size of a contract creation transaction must be within
444
    limits of the protocol.
445
446
    This function takes a transaction as a parameter and returns the intrinsic
447
    gas cost of the transaction after validation. It throws an
448
    `InsufficientTransactionGasError` exception if the transaction does not
449
    provide enough gas to cover the intrinsic cost, and a `NonceOverflowError`
450
    exception if the nonce is greater than `2**64 - 2`. It also raises an
451
    `InitCodeTooLargeError` if the code size of a contract creation transaction
452
    exceeds the maximum allowed size.
453
454
    [EIP-2681]: https://eips.ethereum.org/EIPS/eip-2681
455
    """
456
    from .vm.interpreter import MAX_INIT_CODE_SIZE
457
458
    intrinsic_gas = calculate_intrinsic_cost(tx)
459
    if intrinsic_gas > tx.gas:
460
        raise InsufficientTransactionGasError("Insufficient gas")
461
    if U256(tx.nonce) >= U256(U64.MAX_VALUE):
462
        raise NonceOverflowError("Nonce too high")
463
    if tx.to == Bytes0(b"") and len(tx.data) > MAX_INIT_CODE_SIZE:
464
        raise InitCodeTooLargeError("Code size too large")
465
466
    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 (GAS_TX_BASE)

  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:
470
    """
471
    Calculates the gas that is charged before execution is started.
472
473
    The intrinsic cost of the transaction is charged before execution has
474
    begun. Functions/operations in the EVM cost money to execute so this
475
    intrinsic cost is for the operations that need to be paid for as part of
476
    the transaction. Data transfer, for example, is part of this intrinsic
477
    cost. It costs ether to send data over the wire and that ether is
478
    accounted for in the intrinsic cost calculated in this function. This
479
    intrinsic cost must be calculated and paid for before execution in order
480
    for all operations to be implemented.
481
482
    The intrinsic cost includes:
483
    1. Base cost (`GAS_TX_BASE`)
484
    2. Cost for data (zero and non-zero bytes)
485
    3. Cost for contract creation (if applicable)
486
    4. Cost for access list entries (if applicable)
487
488
    This function takes a transaction as a parameter and returns the intrinsic
489
    gas cost of the transaction.
490
    """
491
    from .vm.gas import init_code_cost
492
493
    num_zeros = Uint(tx.data.count(0))
494
    num_non_zeros = ulen(tx.data) - num_zeros
495
    data_cost = (
496
        num_zeros * GAS_TX_DATA_PER_ZERO
497
        + num_non_zeros * GAS_TX_DATA_PER_NON_ZERO
498
    )
499
500
    if tx.to == Bytes0(b""):
501
        create_cost = GAS_TX_CREATE + init_code_cost(ulen(tx.data))
502
    else:
503
        create_cost = Uint(0)
504
505
    access_list_cost = Uint(0)
406
    if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
506
    if isinstance(
507
        tx, (AccessListTransaction, FeeMarketTransaction, BlobTransaction)
508
    ):
509
        for access in tx.access_list:
510
            access_list_cost += GAS_TX_ACCESS_LIST_ADDRESS
511
            access_list_cost += (
512
                ulen(access.slots) * GAS_TX_ACCESS_LIST_STORAGE_KEY
513
            )
514
515
    return GAS_TX_BASE + 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:
519
    """
520
    Extracts the sender address from a transaction.
521
522
    The v, r, and s values are the three parts that make up the signature
523
    of a transaction. In order to recover the sender of a transaction the two
524
    components needed are the signature (``v``, ``r``, and ``s``) and the
525
    signing hash of the transaction. The sender's public key can be obtained
526
    with these two values and therefore the sender address can be retrieved.
527
528
    This function takes chain_id and a transaction as parameters and returns
529
    the address of the sender of the transaction. It raises an
530
    `InvalidSignatureError` if the signature values (r, s, v) are invalid.
531
    """
532
    r, s = tx.r, tx.s
533
    if U256(0) >= r or r >= SECP256K1N:
534
        raise InvalidSignatureError("bad r")
535
    if U256(0) >= s or s > SECP256K1N // U256(2):
536
        raise InvalidSignatureError("bad s")
537
538
    if isinstance(tx, LegacyTransaction):
539
        v = tx.v
540
        if v == 27 or v == 28:
541
            public_key = secp256k1_recover(
542
                r, s, v - U256(27), signing_hash_pre155(tx)
543
            )
544
        else:
545
            chain_id_x2 = U256(chain_id) * U256(2)
546
            if v != U256(35) + chain_id_x2 and v != U256(36) + chain_id_x2:
547
                raise InvalidSignatureError("bad v")
548
            public_key = secp256k1_recover(
549
                r,
550
                s,
551
                v - U256(35) - chain_id_x2,
552
                signing_hash_155(tx, chain_id),
553
            )
554
    elif isinstance(tx, AccessListTransaction):
555
        if tx.y_parity not in (U256(0), U256(1)):
556
            raise InvalidSignatureError("bad y_parity")
557
        public_key = secp256k1_recover(
558
            r, s, tx.y_parity, signing_hash_2930(tx)
559
        )
560
    elif isinstance(tx, FeeMarketTransaction):
561
        if tx.y_parity not in (U256(0), U256(1)):
562
            raise InvalidSignatureError("bad y_parity")
563
        public_key = secp256k1_recover(
564
            r, s, tx.y_parity, signing_hash_1559(tx)
463
        )
565
        )
566
    elif isinstance(tx, BlobTransaction):
567
        if tx.y_parity not in (U256(0), U256(1)):
568
            raise InvalidSignatureError("bad y_parity")
569
        public_key = secp256k1_recover(
570
            r, s, tx.y_parity, signing_hash_4844(tx)
571
        )
572
573
    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:
577
    """
578
    Compute the hash of a transaction used in a legacy (pre [EIP-155])
579
    signature.
580
581
    This function takes a legacy transaction as a parameter and returns the
582
    signing hash of the transaction.
583
584
    [EIP-155]: https://eips.ethereum.org/EIPS/eip-155
585
    """
586
    return keccak256(
587
        rlp.encode(
588
            (
589
                tx.nonce,
590
                tx.gas_price,
591
                tx.gas,
592
                tx.to,
593
                tx.value,
594
                tx.data,
595
            )
596
        )
597
    )

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:
601
    """
602
    Compute the hash of a transaction used in a [EIP-155] signature.
603
604
    This function takes a legacy transaction and a chain ID as parameters
605
    and returns the hash of the transaction used in an [EIP-155] signature.
606
607
    [EIP-155]: https://eips.ethereum.org/EIPS/eip-155
608
    """
609
    return keccak256(
610
        rlp.encode(
611
            (
612
                tx.nonce,
613
                tx.gas_price,
614
                tx.gas,
615
                tx.to,
616
                tx.value,
617
                tx.data,
618
                chain_id,
619
                Uint(0),
620
                Uint(0),
621
            )
622
        )
623
    )

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:
627
    """
628
    Compute the hash of a transaction used in a [EIP-2930] signature.
629
630
    This function takes an access list transaction as a parameter
631
    and returns the hash of the transaction used in an [EIP-2930] signature.
632
633
    [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930
634
    """
635
    return keccak256(
636
        b"\x01"
637
        + rlp.encode(
638
            (
639
                tx.chain_id,
640
                tx.nonce,
641
                tx.gas_price,
642
                tx.gas,
643
                tx.to,
644
                tx.value,
645
                tx.data,
646
                tx.access_list,
647
            )
648
        )
649
    )

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:
653
    """
654
    Compute the hash of a transaction used in an [EIP-1559] signature.
655
656
    This function takes a fee market transaction as a parameter
657
    and returns the hash of the transaction used in an [EIP-1559] signature.
658
659
    [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559
660
    """
661
    return keccak256(
662
        b"\x02"
663
        + rlp.encode(
664
            (
665
                tx.chain_id,
666
                tx.nonce,
667
                tx.max_priority_fee_per_gas,
668
                tx.max_fee_per_gas,
669
                tx.gas,
670
                tx.to,
671
                tx.value,
672
                tx.data,
673
                tx.access_list,
674
            )
675
        )
676
    )

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:
680
    """
681
    Compute the hash of a transaction used in an [EIP-4844] signature.
682
683
    This function takes a transaction as a parameter and returns the
684
    signing hash of the transaction used in an [EIP-4844] signature.
685
686
    [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844
687
    """
688
    return keccak256(
689
        b"\x03"
690
        + rlp.encode(
691
            (
692
                tx.chain_id,
693
                tx.nonce,
694
                tx.max_priority_fee_per_gas,
695
                tx.max_fee_per_gas,
696
                tx.gas,
697
                tx.to,
698
                tx.value,
699
                tx.data,
700
                tx.access_list,
701
                tx.max_fee_per_blob_gas,
702
                tx.blob_versioned_hashes,
703
            )
704
        )
705
    )

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: Bytes | LegacyTransaction) -> Hash32:
709
    """
710
    Compute the hash of a transaction.
711
712
    This function takes a transaction as a parameter and returns the
713
    keccak256 hash of the transaction. It can handle both legacy transactions
714
    and typed transactions (`AccessListTransaction`, `FeeMarketTransaction`,
715
    etc.).
716
    """
717
    assert isinstance(tx, (LegacyTransaction, Bytes))
718
    if isinstance(tx, LegacyTransaction):
719
        return keccak256(rlp.encode(tx))
720
    else:
721
        return keccak256(tx)