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.

TX_BASE_COST

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

26
TX_BASE_COST = Uint(21000)

TX_DATA_COST_PER_NON_ZERO

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

32
TX_DATA_COST_PER_NON_ZERO = Uint(16)

TX_DATA_COST_PER_ZERO

Gas cost per zero byte in the transaction data.

37
TX_DATA_COST_PER_ZERO = Uint(4)

TX_CREATE_COST

Additional gas cost for creating a new contract.

42
TX_CREATE_COST = Uint(32000)

TX_ACCESS_LIST_ADDRESS_COST

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

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

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

58
@slotted_freezable
59
@dataclass
class LegacyTransaction:

nonce

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

71
    nonce: U256

gas_price

The price of gas for this transaction, in wei.

76
    gas_price: Uint

gas

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

81
    gas: Uint

to

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

86
    to: Bytes0 | Address

value

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

92
    value: U256

data

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

97
    data: Bytes

v

The recovery id of the signature.

103
    v: U256

r

The first part of the signature.

108
    r: U256

s

The second part of the signature.

113
    s: U256

Access

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

119
@slotted_freezable
120
@dataclass
class Access:

account

The address of the account that is accessed.

127
    account: Address

slots

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

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

138
@slotted_freezable
139
@dataclass
class AccessListTransaction:

chain_id

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

151
    chain_id: U64

nonce

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

156
    nonce: U256

gas_price

The price of gas for this transaction.

161
    gas_price: Uint

gas

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

166
    gas: Uint

to

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

171
    to: Bytes0 | Address

value

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

177
    value: U256

data

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

182
    data: Bytes

access_list

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

188
    access_list: Tuple[Access, ...]

y_parity

The recovery id of the signature.

194
    y_parity: U256

r

The first part of the signature.

199
    r: U256

s

The second part of the signature.

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

210
@slotted_freezable
211
@dataclass
class FeeMarketTransaction:

chain_id

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

222
    chain_id: U64

nonce

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

227
    nonce: U256

max_priority_fee_per_gas

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

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

237
    max_fee_per_gas: Uint

gas

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

243
    gas: Uint

to

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

248
    to: Bytes0 | Address

value

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

254
    value: U256

data

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

259
    data: Bytes

access_list

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

265
    access_list: Tuple[Access, ...]

y_parity

The recovery id of the signature.

271
    y_parity: U256

r

The first part of the signature.

276
    r: U256

s

The second part of the signature.

281
    s: U256

BlobTransaction

The transaction type added in EIP-4844.

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

287
@slotted_freezable
288
@dataclass
class BlobTransaction:

chain_id

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

299
    chain_id: U64

nonce

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

304
    nonce: U256

max_priority_fee_per_gas

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

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

314
    max_fee_per_gas: Uint

gas

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

320
    gas: Uint

to

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

325
    to: Address

value

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

331
    value: U256

data

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

336
    data: Bytes

access_list

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

342
    access_list: Tuple[Access, ...]

max_fee_per_blob_gas

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

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

353
    blob_versioned_hashes: Tuple[VersionedHash, ...]

y_parity

The recovery id of the signature.

359
    y_parity: U256

r

The first part of the signature.

364
    r: U256

s

The second part of the signature.

369
    s: U256

Transaction

Union type representing any valid transaction type.

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

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:
387
    """
388
    Encode a transaction into its RLP or typed transaction format.
389
    Needed because non-legacy transactions aren't RLP.
390
391
    Legacy transactions are returned as-is, while other transaction types
392
    are prefixed with their type identifier and RLP encoded.
393
    """
394
    if isinstance(tx, LegacyTransaction):
395
        return tx
396
    elif isinstance(tx, AccessListTransaction):
397
        return b"\x01" + rlp.encode(tx)
398
    elif isinstance(tx, FeeMarketTransaction):
399
        return b"\x02" + rlp.encode(tx)
305
    else:
306
        raise Exception(f"Unable to encode transaction of type {type(tx)}")
400
    elif isinstance(tx, BlobTransaction):
401
        return b"\x03" + rlp.encode(tx)
402
    else:
403
        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:
407
    """
408
    Decode a transaction from its RLP or typed transaction format.
409
    Needed because non-legacy transactions aren't RLP.
410
411
    Legacy transactions are returned as-is, while other transaction types
412
    are decoded based on their type identifier prefix.
413
    """
414
    if isinstance(tx, Bytes):
415
        if tx[0] == 1:
416
            return rlp.decode_to(AccessListTransaction, tx[1:])
417
        elif tx[0] == 2:
418
            return rlp.decode_to(FeeMarketTransaction, tx[1:])
322
        else:
323
            raise TransactionTypeError(tx[0])
419
        elif tx[0] == 3:
420
            return rlp.decode_to(BlobTransaction, tx[1:])
421
        else:
422
            raise TransactionTypeError(tx[0])
423
    else:
424
        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:
428
    """
429
    Verifies a transaction.
430
431
    The gas in a transaction gets used to pay for the intrinsic cost of
432
    operations, therefore if there is insufficient gas then it would not
433
    be possible to execute a transaction and it will be declared invalid.
434
435
    Additionally, the nonce of a transaction must not equal or exceed the
436
    limit defined in [EIP-2681].
437
    In practice, defining the limit as ``2**64-1`` has no impact because
438
    sending ``2**64-1`` transactions is improbable. It's not strictly
439
    impossible though, ``2**64-1`` transactions is the entire capacity of the
440
    Ethereum blockchain at 2022 gas limits for a little over 22 years.
441
442
    Also, the code size of a contract creation transaction must be within
443
    limits of the protocol.
444
445
    This function takes a transaction as a parameter and returns the intrinsic
446
    gas cost of the transaction after validation. It throws an
447
    `InsufficientTransactionGasError` exception if the transaction does not
448
    provide enough gas to cover the intrinsic cost, and a `NonceOverflowError`
449
    exception if the nonce is greater than `2**64 - 2`. It also raises an
450
    `InitCodeTooLargeError` if the code size of a contract creation transaction
451
    exceeds the maximum allowed size.
452
453
    [EIP-2681]: https://eips.ethereum.org/EIPS/eip-2681
454
    """
455
    from .vm.interpreter import MAX_INIT_CODE_SIZE
456
457
    intrinsic_gas = calculate_intrinsic_cost(tx)
458
    if intrinsic_gas > tx.gas:
459
        raise InsufficientTransactionGasError("Insufficient gas")
460
    if U256(tx.nonce) >= U256(U64.MAX_VALUE):
461
        raise NonceOverflowError("Nonce too high")
462
    if tx.to == Bytes0(b"") and len(tx.data) > MAX_INIT_CODE_SIZE:
463
        raise InitCodeTooLargeError("Code size too large")
464
465
    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:
469
    """
470
    Calculates the gas that is charged before execution is started.
471
472
    The intrinsic cost of the transaction is charged before execution has
473
    begun. Functions/operations in the EVM cost money to execute so this
474
    intrinsic cost is for the operations that need to be paid for as part of
475
    the transaction. Data transfer, for example, is part of this intrinsic
476
    cost. It costs ether to send data over the wire and that ether is
477
    accounted for in the intrinsic cost calculated in this function. This
478
    intrinsic cost must be calculated and paid for before execution in order
479
    for all operations to be implemented.
480
481
    The intrinsic cost includes:
482
    1. Base cost (`TX_BASE_COST`)
483
    2. Cost for data (zero and non-zero bytes)
484
    3. Cost for contract creation (if applicable)
485
    4. Cost for access list entries (if applicable)
486
487
    This function takes a transaction as a parameter and returns the intrinsic
488
    gas cost of the transaction.
489
    """
490
    from .vm.gas import init_code_cost
491
492
    data_cost = Uint(0)
493
494
    for byte in tx.data:
495
        if byte == 0:
496
            data_cost += TX_DATA_COST_PER_ZERO
497
        else:
498
            data_cost += TX_DATA_COST_PER_NON_ZERO
499
500
    if tx.to == Bytes0(b""):
501
        create_cost = TX_CREATE_COST + init_code_cost(ulen(tx.data))
502
    else:
503
        create_cost = Uint(0)
504
505
    access_list_cost = Uint(0)
407
    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 += TX_ACCESS_LIST_ADDRESS_COST
511
            access_list_cost += (
512
                ulen(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST
513
            )
514
515
    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:
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)
464
        )
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)