diff --git a/README.md b/README.md index 95d657f..660705a 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,44 @@ Installing this plugin adds support for the Optimism ecosystem: ape console --network optimism:sepolia ``` +### OP Stack + +Use the `optimism` base-class in any custom networks using the OP stack. +For example, to configure a custom network for Fraxtal network, add the following to your `pyproject.toml` + +```toml +[[tool.ape.networks.custom]] +name = "mainnet" +ecosystem = "fraxtal" +# Tell Ape to use optimism as the base plugin, instead of ethereum. +base_ecosystem_plugin = "optimism" +chain_id = 252 + +# (optional): Configure an RPC. Else, Ape will select a random one automatically. +[tool.ape.node.fraxtal.mainnet] +uri = "https://rpc.frax.com" +``` + +Or equivalent `ape-config.yaml`: + +```yaml +networks: + custom: + - name: mainnet + ecosystem: fraxtal + base_ecosystem_plugin: optimism + +node: + fraxtal: + mainnet: + uri: https://rpc.frax.com +``` + +There are two main benefits of using Optimism as the base-class instead of Ethereum for networks using the OP stack: + +1. **Closer defaults**: The block time default is `2` for Optimism networks, which may be a better default value than Ethereum's higher block time parameters. +2. **Existence of System Transactions**: The Optimism base-class is aware of system transactions, which are transactions invoked by the sequencer. + ## Development Comments, questions, criticisms and pull requests are welcomed. diff --git a/ape_optimism/ecosystem.py b/ape_optimism/ecosystem.py index 5639dfc..6b1a825 100644 --- a/ape_optimism/ecosystem.py +++ b/ape_optimism/ecosystem.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, cast +from typing import cast from ape.api import TransactionAPI from ape.exceptions import ApeException, APINotImplementedError @@ -8,9 +8,7 @@ NetworkConfig, create_network_config, ) - -if TYPE_CHECKING: - from eth_pydantic_types import HexBytes +from eth_pydantic_types import HexBytes NETWORKS = { # chain_id, network_id @@ -34,16 +32,30 @@ class OptimismConfig(BaseEthereumConfig): class SystemTransaction(TransactionAPI): type: int = SYSTEM_TRANSACTION + _hash: HexBytes + + def __init__(self, *args, **kwargs): + hash = kwargs.pop("hash", None) + super().__init__(*args, **kwargs) + self._hash = hash @property def txn_hash(self) -> "HexBytes": - raise APINotImplementedError("Unable to calculate the hash of system transactions.") + return self._hash def serialize_transaction(self) -> bytes: raise APINotImplementedError("Unable to serialize system transactions.") class Optimism(Ethereum): + """ + A base class for Optimism or OP-stack networks. + The main differences from Ethereum are: + + 1. Different network defaults (block time is only '2', by default). + 2. Recognition of "System transactions" (type 126). + """ + @property def config(self) -> OptimismConfig: # type: ignore return cast(OptimismConfig, self.config_manager.get_config("optimism")) diff --git a/tests/test_ecosystem.py b/tests/test_ecosystem.py index 1d47b6c..0b77236 100644 --- a/tests/test_ecosystem.py +++ b/tests/test_ecosystem.py @@ -1,6 +1,7 @@ import pytest from ape_ethereum.transactions import TransactionType from ethpm_types.abi import MethodABI +from hexbytes import HexBytes from ape_optimism.ecosystem import SYSTEM_TRANSACTION, SystemTransaction @@ -45,6 +46,7 @@ def test_create_transaction_type_2(optimism, tx_kwargs): def test_create_transaction_type_126(optimism): + txn_hash = "0x417b3339801514042a4b3fa24658931438389996b29d0749cc7555a13a9ad89a" data = { "chainId": 0, "to": "0x4200000000000000000000000000000000000015", @@ -55,10 +57,12 @@ def test_create_transaction_type_126(optimism): "data": "0x", "type": 126, "accessList": [], + "hash": HexBytes(txn_hash), } actual = optimism.create_transaction(**data) assert isinstance(actual, SystemTransaction) assert actual.type == SYSTEM_TRANSACTION + assert actual.txn_hash == HexBytes(txn_hash) @pytest.mark.parametrize(