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

IntrinsicGasCost

Intrinsic gas costs for a transaction, split by gas type.

28
@final
29
@dataclass
class IntrinsicGasCost:

regular

Regular execution gas (calldata, base cost, access list, etc.).

33
    regular: Uint

calldata_floor

Minimum gas cost based on calldata size per EIP-7623.

36
    calldata_floor: Uint

LegacyTransaction

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

44
@final
45
@slotted_freezable
46
@dataclass
class LegacyTransaction:

nonce

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

59
    nonce: U256

gas_price

The price of gas for this transaction, in wei.

64
    gas_price: Uint

gas

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

69
    gas: Uint

to

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

74
    to: Bytes0 | Address

value

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

80
    value: U256

data

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

85
    data: Bytes

v

The recovery id of the signature.

91
    v: U256

r

The first part of the signature.

96
    r: U256

s

The second part of the signature.

101
    s: U256

Access

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

107
@final
108
@slotted_freezable
109
@dataclass
class Access:

account

The address of the account that is accessed.

116
    account: Address

slots

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

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

127
@final
128
@slotted_freezable
129
@dataclass
class AccessListTransaction:

chain_id

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

141
    chain_id: U64

nonce

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

146
    nonce: U256

gas_price

The price of gas for this transaction.

151
    gas_price: Uint

gas

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

156
    gas: Uint

to

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

161
    to: Bytes0 | Address

value

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

167
    value: U256

data

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

172
    data: Bytes

access_list

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

178
    access_list: Tuple[Access, ...]

y_parity

The recovery id of the signature.

184
    y_parity: U256

r

The first part of the signature.

189
    r: U256

s

The second part of the signature.

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

200
@final
201
@slotted_freezable
202
@dataclass
class FeeMarketTransaction:

chain_id

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

213
    chain_id: U64

nonce

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

218
    nonce: U256

max_priority_fee_per_gas

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

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

228
    max_fee_per_gas: Uint

gas

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

234
    gas: Uint

to

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

239
    to: Bytes0 | Address

value

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

245
    value: U256

data

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

250
    data: Bytes

access_list

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

256
    access_list: Tuple[Access, ...]

y_parity

The recovery id of the signature.

262
    y_parity: U256

r

The first part of the signature.

267
    r: U256

s

The second part of the signature.

272
    s: U256

BlobTransaction

The transaction type added in EIP-4844.

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

278
@final
279
@slotted_freezable
280
@dataclass
class BlobTransaction:

chain_id

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

291
    chain_id: U64

nonce

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

296
    nonce: U256

max_priority_fee_per_gas

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

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

306
    max_fee_per_gas: Uint

gas

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

312
    gas: Uint

to

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

317
    to: Address

value

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

323
    value: U256

data

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

328
    data: Bytes

access_list

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

334
    access_list: Tuple[Access, ...]

max_fee_per_blob_gas

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

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

345
    blob_versioned_hashes: Tuple[VersionedHash, ...]

y_parity

The recovery id of the signature.

351
    y_parity: U256

r

The first part of the signature.

356
    r: U256

s

The second part of the signature.

361
    s: U256

SetCodeTransaction

The transaction type added in EIP-7702.

This transaction type allows Ethereum Externally Owned Accounts (EOAs) to set code on their account, enabling them to act as smart contracts.

367
@final
368
@slotted_freezable
369
@dataclass
class SetCodeTransaction:

chain_id

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

380
    chain_id: U64

nonce

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

385
    nonce: U64

max_priority_fee_per_gas

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

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

395
    max_fee_per_gas: Uint

gas

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

401
    gas: Uint

to

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

406
    to: Address

value

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

412
    value: U256

data

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

417
    data: Bytes

access_list

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

423
    access_list: Tuple[Access, ...]

authorizations

A tuple of Authorization objects that specify what code the signer desires to execute in the context of their EOA.

429
    authorizations: Tuple[Authorization, ...]

y_parity

The recovery id of the signature.

435
    y_parity: U256

r

The first part of the signature.

440
    r: U256

s

The second part of the signature.

445
    s: U256

Transaction

Union type representing any valid transaction type.

451
Transaction = (
351
    LegacyTransaction
352
    | AccessListTransaction
353
    | FeeMarketTransaction
354
    | BlobTransaction
452
    LegacyTransaction
453
    | AccessListTransaction
454
    | FeeMarketTransaction
455
    | BlobTransaction
456
    | SetCodeTransaction
457
)

AccessListCapableTransaction

Transaction types that include an EIP-2930-style access list.

See has_access_list and Access for more details.

463
AccessListCapableTransaction = (
464
    AccessListTransaction
465
    | FeeMarketTransaction
466
    | BlobTransaction
467
    | SetCodeTransaction
468
)

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:
481
    <snip>
488
    if isinstance(tx, LegacyTransaction):
489
        return tx
490
    elif isinstance(tx, AccessListTransaction):
491
        return b"\x01" + rlp.encode(tx)
492
    elif isinstance(tx, FeeMarketTransaction):
493
        return b"\x02" + rlp.encode(tx)
494
    elif isinstance(tx, BlobTransaction):
495
        return b"\x03" + rlp.encode(tx)
377
    else:
378
        raise Exception(f"Unable to encode transaction of type {type(tx)}")
496
    elif isinstance(tx, SetCodeTransaction):
497
        return b"\x04" + rlp.encode(tx)
498
    else:
499
        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:
503
    <snip>
510
    if isinstance(tx, Bytes):
511
        if tx[0] == 1:
512
            return rlp.decode_to(AccessListTransaction, tx[1:])
513
        elif tx[0] == 2:
514
            return rlp.decode_to(FeeMarketTransaction, tx[1:])
515
        elif tx[0] == 3:
516
            return rlp.decode_to(BlobTransaction, tx[1:])
396
        else:
397
            raise TransactionTypeError(tx[0])
517
        elif tx[0] == 4:
518
            return rlp.decode_to(SetCodeTransaction, tx[1:])
519
        else:
520
            raise TransactionTypeError(tx[0])
521
    else:
522
        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 angas cost and the minimum calldata gas cost for the transaction after validation. It throws an InsufficientTransactionGasError exception if the transaction does not exception if provide enough gas to cover the intrinsic cost, and a the transaction does not provide enough gas to cover the intrinsic cost, and a NonceOverflowError exception if the nonce is greater than exception if the nonce is greater than 2**64 - 2. It also raises an. It also raises an InitCodeTooLargeError if the code size of InitCodeTooLargeError if the code size of a contract creation transaction exceeds the maximum allowed size.a contract creation transaction exceeds the maximum allowed size.

def validate_transaction(tx: Transaction) -> UintIntrinsicGasCost:
526
    <snip>
554
    from .vm.interpreter import MAX_INIT_CODE_SIZE
555
432
    intrinsic_gas = calculate_intrinsic_cost(tx)
433
    if intrinsic_gas > tx.gas:
556
    intrinsic = calculate_intrinsic_cost(tx)
557
    if max(intrinsic.regular, intrinsic.calldata_floor) > tx.gas:
558
        raise InsufficientTransactionGasError("Insufficient gas")
559
    if U256(tx.nonce) >= U256(U64.MAX_VALUE):
560
        raise NonceOverflowError("Nonce too high")
561
    if tx.to == Bytes0(b"") and len(tx.data) > MAX_INIT_CODE_SIZE:
562
        raise InitCodeTooLargeError("Code size too large")
563
440
    return intrinsic_gas
564
    return intrinsic

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)

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

  3. Cost for contract creation (if applicable)

  4. Cost for access list entries (if applicable)

  5. Cost for authorizations (if applicable)

This function takes a transaction as a parameter and returns the intrinsic gas cost of the transaction.gas cost of the transaction and the minimum gas cost used by the transaction based on the calldata size.

def calculate_intrinsic_cost(tx: Transaction) -> UintIntrinsicGasCost:
568
    <snip>
592
    from .vm.gas import GasCosts, init_code_cost
593
594
    num_zeros = Uint(tx.data.count(0))
595
    num_non_zeros = ulen(tx.data) - num_zeros
469
    data_cost = (
470
        num_zeros * GasCosts.TX_DATA_PER_ZERO
471
        + num_non_zeros * GasCosts.TX_DATA_PER_NON_ZERO
596
597
    tokens_in_calldata = num_zeros + num_non_zeros * Uint(4)
598
    # EIP-7623 floor price (note: no EVM costs)
599
    calldata_floor_gas_cost = (
600
        tokens_in_calldata * GasCosts.TX_DATA_TOKEN_FLOOR + GasCosts.TX_BASE
601
    )
602
603
    data_cost = tokens_in_calldata * GasCosts.TX_DATA_TOKEN_STANDARD
604
605
    if tx.to == Bytes0(b""):
606
        create_cost = GasCosts.TX_CREATE + init_code_cost(ulen(tx.data))
607
    else:
608
        create_cost = Uint(0)
609
610
    access_list_cost = Uint(0)
480
    if isinstance(
481
        tx, (AccessListTransaction, FeeMarketTransaction, BlobTransaction)
482
    ):
611
    if has_access_list(tx):
612
        for access in tx.access_list:
613
            access_list_cost += GasCosts.TX_ACCESS_LIST_ADDRESS
614
            access_list_cost += (
615
                ulen(access.slots) * GasCosts.TX_ACCESS_LIST_STORAGE_KEY
616
            )
617
489
    return GasCosts.TX_BASE + data_cost + create_cost + access_list_cost
618
    auth_cost = Uint(0)
619
    if isinstance(tx, SetCodeTransaction):
620
        auth_cost += Uint(
621
            GasCosts.AUTH_PER_EMPTY_ACCOUNT * len(tx.authorizations)
622
        )
623
624
    return IntrinsicGasCost(
625
        regular=Uint(
626
            GasCosts.TX_BASE
627
            + data_cost
628
            + create_cost
629
            + access_list_cost
630
            + auth_cost
631
        ),
632
        calldata_floor=calldata_floor_gas_cost,
633
    )

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:
637
    <snip>
650
    r, s = tx.r, tx.s
651
    if U256(0) >= r or r >= SECP256K1N:
652
        raise InvalidSignatureError("bad r")
653
    if U256(0) >= s or s > SECP256K1N // U256(2):
654
        raise InvalidSignatureError("bad s")
655
656
    if isinstance(tx, LegacyTransaction):
657
        v = tx.v
658
        if v == 27 or v == 28:
659
            public_key = secp256k1_recover(
660
                r, s, v - U256(27), signing_hash_pre155(tx)
661
            )
662
        else:
663
            chain_id_x2 = U256(chain_id) * U256(2)
664
            if v != U256(35) + chain_id_x2 and v != U256(36) + chain_id_x2:
665
                raise InvalidSignatureError("bad v")
666
            public_key = secp256k1_recover(
667
                r,
668
                s,
669
                v - U256(35) - chain_id_x2,
670
                signing_hash_155(tx, chain_id),
671
            )
672
    elif isinstance(tx, AccessListTransaction):
673
        if tx.y_parity not in (U256(0), U256(1)):
674
            raise InvalidSignatureError("bad y_parity")
675
        public_key = secp256k1_recover(
676
            r, s, tx.y_parity, signing_hash_2930(tx)
677
        )
678
    elif isinstance(tx, FeeMarketTransaction):
679
        if tx.y_parity not in (U256(0), U256(1)):
680
            raise InvalidSignatureError("bad y_parity")
681
        public_key = secp256k1_recover(
682
            r, s, tx.y_parity, signing_hash_1559(tx)
683
        )
684
    elif isinstance(tx, BlobTransaction):
685
        if tx.y_parity not in (U256(0), U256(1)):
686
            raise InvalidSignatureError("bad y_parity")
687
        public_key = secp256k1_recover(
688
            r, s, tx.y_parity, signing_hash_4844(tx)
545
        )
689
        )
690
    elif isinstance(tx, SetCodeTransaction):
691
        if tx.y_parity not in (U256(0), U256(1)):
692
            raise InvalidSignatureError("bad y_parity")
693
        public_key = secp256k1_recover(
694
            r, s, tx.y_parity, signing_hash_7702(tx)
695
        )
696
697
    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:
701
    <snip>
710
    return keccak256(
711
        rlp.encode(
712
            (
713
                tx.nonce,
714
                tx.gas_price,
715
                tx.gas,
716
                tx.to,
717
                tx.value,
718
                tx.data,
719
            )
720
        )
721
    )

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:
725
    <snip>
733
    return keccak256(
734
        rlp.encode(
735
            (
736
                tx.nonce,
737
                tx.gas_price,
738
                tx.gas,
739
                tx.to,
740
                tx.value,
741
                tx.data,
742
                chain_id,
743
                Uint(0),
744
                Uint(0),
745
            )
746
        )
747
    )

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:
751
    <snip>
759
    return keccak256(
760
        b"\x01"
761
        + rlp.encode(
762
            (
763
                tx.chain_id,
764
                tx.nonce,
765
                tx.gas_price,
766
                tx.gas,
767
                tx.to,
768
                tx.value,
769
                tx.data,
770
                tx.access_list,
771
            )
772
        )
773
    )

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:
777
    <snip>
785
    return keccak256(
786
        b"\x02"
787
        + rlp.encode(
788
            (
789
                tx.chain_id,
790
                tx.nonce,
791
                tx.max_priority_fee_per_gas,
792
                tx.max_fee_per_gas,
793
                tx.gas,
794
                tx.to,
795
                tx.value,
796
                tx.data,
797
                tx.access_list,
798
            )
799
        )
800
    )

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:
804
    <snip>
812
    return keccak256(
813
        b"\x03"
814
        + rlp.encode(
815
            (
816
                tx.chain_id,
817
                tx.nonce,
818
                tx.max_priority_fee_per_gas,
819
                tx.max_fee_per_gas,
820
                tx.gas,
821
                tx.to,
822
                tx.value,
823
                tx.data,
824
                tx.access_list,
825
                tx.max_fee_per_blob_gas,
826
                tx.blob_versioned_hashes,
827
            )
828
        )
829
    )

signing_hash_7702

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

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

def signing_hash_7702(tx: SetCodeTransaction) -> Hash32:
833
    <snip>
841
    return keccak256(
842
        b"\x04"
843
        + rlp.encode(
844
            (
845
                tx.chain_id,
846
                tx.nonce,
847
                tx.max_priority_fee_per_gas,
848
                tx.max_fee_per_gas,
849
                tx.gas,
850
                tx.to,
851
                tx.value,
852
                tx.data,
853
                tx.access_list,
854
                tx.authorizations,
855
            )
856
        )
857
    )

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:
861
    <snip>
869
    assert isinstance(tx, (LegacyTransaction, Bytes))
870
    if isinstance(tx, LegacyTransaction):
871
        return keccak256(rlp.encode(tx))
872
    else:
873
        return keccak256(tx)

has_access_list

Return whether the transaction has an EIP-2930-style access list.

def has_access_list(tx: Transaction) -> TypeGuard[AccessListCapableTransaction]:
879
    <snip>
884
    return isinstance(
885
        tx,
886
        AccessListCapableTransaction,
887
    )