From 13c1a1abe57c837f046fbbca8cb8a0afcabc259c Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Thu, 7 Mar 2024 08:55:14 -0800 Subject: [PATCH 1/9] feat: drop istanbul support --- docs/compiling-a-contract.rst | 8 +------- tests/functional/syntax/test_self_balance.py | 5 +---- tests/unit/cli/vyper_json/test_get_settings.py | 3 ++- tests/unit/compiler/test_opcodes.py | 16 +++++++--------- vyper/cli/vyper_json.py | 3 ++- vyper/codegen/expr.py | 11 +---------- vyper/evm/opcodes.py | 4 ++-- 7 files changed, 16 insertions(+), 34 deletions(-) diff --git a/docs/compiling-a-contract.rst b/docs/compiling-a-contract.rst index c4e8bad636..8589955273 100644 --- a/docs/compiling-a-contract.rst +++ b/docs/compiling-a-contract.rst @@ -176,12 +176,6 @@ Target Options The following is a list of supported EVM versions, and changes in the compiler introduced with each version. Backward compatibility is not guaranteed between each version. -.. py:attribute:: istanbul - - - The ``CHAINID`` opcode is accessible via ``chain.id`` - - The ``SELFBALANCE`` opcode is used for calls to ``self.balance`` - - Gas estimates changed for ``SLOAD`` and ``BALANCE`` - .. py:attribute:: berlin - Gas estimates changed for ``EXTCODESIZE``, ``EXTCODECOPY``, ``EXTCODEHASH``, ``SLOAD``, ``SSTORE``, ``CALL``, ``CALLCODE``, ``DELEGATECALL`` and ``STATICCALL`` @@ -247,7 +241,7 @@ The following example describes the expected input format of ``vyper-json``. Com }, // Optional "settings": { - "evmVersion": "shanghai", // EVM version to compile for. Can be istanbul, berlin, paris, shanghai (default) or cancun (experimental!). + "evmVersion": "shanghai", // EVM version to compile for. Can be berlin, london, paris, shanghai (default) or cancun (experimental!). // optional, optimization mode // defaults to "gas". can be one of "gas", "codesize", "none", // false and true (the last two are for backwards compatibility). diff --git a/tests/functional/syntax/test_self_balance.py b/tests/functional/syntax/test_self_balance.py index d22d8a2750..28cbd05453 100644 --- a/tests/functional/syntax/test_self_balance.py +++ b/tests/functional/syntax/test_self_balance.py @@ -21,10 +21,7 @@ def __default__(): """ settings = Settings(evm_version=evm_version) opcodes = compiler.compile_code(code, output_formats=["opcodes"], settings=settings)["opcodes"] - if EVM_VERSIONS[evm_version] >= EVM_VERSIONS["istanbul"]: - assert "SELFBALANCE" in opcodes - else: - assert "SELFBALANCE" not in opcodes + assert "SELFBALANCE" in opcodes c = get_contract_with_gas_estimation(code, evm_version=evm_version) w3.eth.send_transaction({"to": c.address, "value": 1337}) diff --git a/tests/unit/cli/vyper_json/test_get_settings.py b/tests/unit/cli/vyper_json/test_get_settings.py index 989d4565cd..65ea43456c 100644 --- a/tests/unit/cli/vyper_json/test_get_settings.py +++ b/tests/unit/cli/vyper_json/test_get_settings.py @@ -18,6 +18,7 @@ def test_unknown_evm(): "byzantium", "constantinople", "petersburg", + "istanbul", ], ) def test_early_evm(evm_version): @@ -25,6 +26,6 @@ def test_early_evm(evm_version): get_evm_version({"settings": {"evmVersion": evm_version}}) -@pytest.mark.parametrize("evm_version", ["istanbul", "berlin", "paris", "shanghai", "cancun"]) +@pytest.mark.parametrize("evm_version", ["berlin", "london", "paris", "shanghai", "cancun"]) def test_valid_evm(evm_version): assert evm_version == get_evm_version({"settings": {"evmVersion": evm_version}}) diff --git a/tests/unit/compiler/test_opcodes.py b/tests/unit/compiler/test_opcodes.py index ed64f343c4..1976d8ba94 100644 --- a/tests/unit/compiler/test_opcodes.py +++ b/tests/unit/compiler/test_opcodes.py @@ -38,10 +38,12 @@ def test_version_check(evm_version): assert opcodes.version_check(begin=evm_version) assert opcodes.version_check(end=evm_version) assert opcodes.version_check(begin=evm_version, end=evm_version) - if evm_version not in ("istanbul"): - assert not opcodes.version_check(end="istanbul") - istanbul_check = opcodes.version_check(begin="istanbul") - assert istanbul_check == (opcodes.EVM_VERSIONS[evm_version] >= opcodes.EVM_VERSIONS["istanbul"]) + if evm_version not in ("berlin"): + assert not opcodes.version_check(end="berlin") + berlin_check = opcodes.version_check(begin="berlin_check") + assert berlin_check == ( + opcodes.EVM_VERSIONS[evm_version] >= opcodes.EVM_VERSIONS["berlin_check"] + ) def test_get_opcodes(evm_version): @@ -50,11 +52,7 @@ def test_get_opcodes(evm_version): assert "CHAINID" in ops assert ops["CREATE2"][-1] == 32000 - if evm_version in ("london", "berlin", "paris", "shanghai", "cancun"): - assert ops["SLOAD"][-1] == 2100 - else: - assert evm_version == "istanbul" - assert ops["SLOAD"][-1] == 800 + assert ops["SLOAD"][-1] == 2100 if evm_version in ("shanghai", "cancun"): assert "PUSH0" in ops diff --git a/vyper/cli/vyper_json.py b/vyper/cli/vyper_json.py index 032d7ebe64..d09b364811 100755 --- a/vyper/cli/vyper_json.py +++ b/vyper/cli/vyper_json.py @@ -143,8 +143,9 @@ def get_evm_version(input_dict: dict) -> Optional[str]: "spuriousDragon", "byzantium", "constantinople", + "istanbul", ): - raise JSONError("Vyper does not support pre-istanbul EVM versions") + raise JSONError("Vyper does not support pre-berlin EVM versions") if evm_version not in EVM_VERSIONS: raise JSONError(f"Unknown EVM version - '{evm_version}'") diff --git a/vyper/codegen/expr.py b/vyper/codegen/expr.py index d0c5154cbe..dc660d25b2 100644 --- a/vyper/codegen/expr.py +++ b/vyper/codegen/expr.py @@ -32,7 +32,6 @@ from vyper.exceptions import ( CodegenPanic, CompilerPanic, - EvmVersionException, StructureException, TypeCheckFailure, TypeMismatch, @@ -230,11 +229,7 @@ def parse_Attribute(self): if self.expr.attr == "balance": addr = Expr.parse_value_expr(self.expr.value, self.context) if addr.typ == AddressT(): - if ( - isinstance(self.expr.value, vy_ast.Name) - and self.expr.value.id == "self" - and version_check(begin="istanbul") - ): + if isinstance(self.expr.value, vy_ast.Name) and self.expr.value.id == "self": seq = ["selfbalance"] else: seq = ["balance", addr] @@ -310,10 +305,6 @@ def parse_Attribute(self): elif key == "tx.gasprice": return IRnode.from_list(["gasprice"], typ=UINT256_T) elif key == "chain.id": - if not version_check(begin="istanbul"): - raise EvmVersionException( - "chain.id is unavailable prior to istanbul ruleset", self.expr - ) return IRnode.from_list(["chainid"], typ=UINT256_T) # Other variables diff --git a/vyper/evm/opcodes.py b/vyper/evm/opcodes.py index 767d634c89..78848971de 100644 --- a/vyper/evm/opcodes.py +++ b/vyper/evm/opcodes.py @@ -11,7 +11,7 @@ # 3. Per VIP-3365, we support mainnet fork choice rules up to 1 year old # (and may optionally have forward support for experimental/unreleased # fork choice rules) -_evm_versions = ("istanbul", "berlin", "london", "paris", "shanghai", "cancun") +_evm_versions = ("berlin", "london", "paris", "shanghai", "cancun") EVM_VERSIONS: dict[str, int] = dict((v, i) for i, v in enumerate(_evm_versions)) @@ -22,7 +22,7 @@ # opcode as hex value # number of values removed from stack # number of values added to stack -# gas cost (istanbul, berlin, paris, shanghai, cancun) +# gas cost (berlin, london, paris, shanghai, cancun) OPCODES: OpcodeMap = { "STOP": (0x00, 0, 0, 0), "ADD": (0x01, 2, 1, 3), From e7756725803d24e199216c7db3cb5b0b827b329a Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Fri, 8 Mar 2024 08:48:18 -0800 Subject: [PATCH 2/9] remove berlin support --- vyper/evm/opcodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vyper/evm/opcodes.py b/vyper/evm/opcodes.py index 78848971de..0a42533383 100644 --- a/vyper/evm/opcodes.py +++ b/vyper/evm/opcodes.py @@ -11,7 +11,7 @@ # 3. Per VIP-3365, we support mainnet fork choice rules up to 1 year old # (and may optionally have forward support for experimental/unreleased # fork choice rules) -_evm_versions = ("berlin", "london", "paris", "shanghai", "cancun") +_evm_versions = ("london", "paris", "shanghai", "cancun") EVM_VERSIONS: dict[str, int] = dict((v, i) for i, v in enumerate(_evm_versions)) From 1f897bd58520302a98fdcdd9661b5819dc0bfa7a Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Fri, 8 Mar 2024 08:50:05 -0800 Subject: [PATCH 3/9] update opcode map --- vyper/evm/opcodes.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/vyper/evm/opcodes.py b/vyper/evm/opcodes.py index 0a42533383..68821136a7 100644 --- a/vyper/evm/opcodes.py +++ b/vyper/evm/opcodes.py @@ -22,7 +22,7 @@ # opcode as hex value # number of values removed from stack # number of values added to stack -# gas cost (berlin, london, paris, shanghai, cancun) +# gas cost (london, paris, shanghai, cancun) OPCODES: OpcodeMap = { "STOP": (0x00, 0, 0, 0), "ADD": (0x01, 2, 1, 3), @@ -62,11 +62,11 @@ "CODESIZE": (0x38, 0, 1, 2), "CODECOPY": (0x39, 3, 0, 3), "GASPRICE": (0x3A, 0, 1, 2), - "EXTCODESIZE": (0x3B, 1, 1, (700, 2600)), - "EXTCODECOPY": (0x3C, 4, 0, (700, 2600)), + "EXTCODESIZE": (0x3B, 1, 1, 2600), + "EXTCODECOPY": (0x3C, 4, 0, 2600), "RETURNDATASIZE": (0x3D, 0, 1, 2), "RETURNDATACOPY": (0x3E, 3, 0, 3), - "EXTCODEHASH": (0x3F, 1, 1, (700, 2600)), + "EXTCODEHASH": (0x3F, 1, 1, 2600), "BLOCKHASH": (0x40, 1, 1, 20), "COINBASE": (0x41, 0, 1, 2), "TIMESTAMP": (0x42, 0, 1, 2), @@ -76,12 +76,12 @@ "GASLIMIT": (0x45, 0, 1, 2), "CHAINID": (0x46, 0, 1, 2), "SELFBALANCE": (0x47, 0, 1, 5), - "BASEFEE": (0x48, 0, 1, (None, 2)), + "BASEFEE": (0x48, 0, 1, 2), "POP": (0x50, 1, 0, 2), "MLOAD": (0x51, 1, 1, 3), "MSTORE": (0x52, 2, 0, 3), "MSTORE8": (0x53, 2, 0, 3), - "SLOAD": (0x54, 1, 1, (800, 2100)), + "SLOAD": (0x54, 1, 1, 2100), "SSTORE": (0x55, 2, 0, 20000), "JUMP": (0x56, 1, 0, 8), "JUMPI": (0x57, 2, 0, 10), @@ -89,7 +89,7 @@ "MSIZE": (0x59, 0, 1, 2), "GAS": (0x5A, 0, 1, 2), "JUMPDEST": (0x5B, 0, 0, 1), - "MCOPY": (0x5E, 3, 0, (None, None, None, None, None, 3)), + "MCOPY": (0x5E, 3, 0, (None, None, None, 3)), "PUSH0": (0x5F, 0, 1, 2), "PUSH1": (0x60, 0, 1, 3), "PUSH2": (0x61, 0, 1, 3), @@ -161,19 +161,19 @@ "LOG3": (0xA3, 5, 0, 1500), "LOG4": (0xA4, 6, 0, 1875), "CREATE": (0xF0, 3, 1, 32000), - "CALL": (0xF1, 7, 1, (700, 2100)), - "CALLCODE": (0xF2, 7, 1, (700, 2100)), + "CALL": (0xF1, 7, 1, 2100), + "CALLCODE": (0xF2, 7, 1, 2100), "RETURN": (0xF3, 2, 0, 0), - "DELEGATECALL": (0xF4, 6, 1, (700, 2100)), + "DELEGATECALL": (0xF4, 6, 1, 2100), "CREATE2": (0xF5, 4, 1, 32000), "SELFDESTRUCT": (0xFF, 1, 0, 25000), - "STATICCALL": (0xFA, 6, 1, (700, 2100)), + "STATICCALL": (0xFA, 6, 1, 2100), "REVERT": (0xFD, 2, 0, 0), "INVALID": (0xFE, 0, 0, 0), "DEBUG": (0xA5, 1, 0, 0), "BREAKPOINT": (0xA6, 0, 0, 0), - "TLOAD": (0x5C, 1, 1, (None, None, None, None, None, 100)), - "TSTORE": (0x5D, 2, 0, (None, None, None, None, None, 100)), + "TLOAD": (0x5C, 1, 1, (None, None, None, 100)), + "TSTORE": (0x5D, 2, 0, (None, None, None, 100)), } PSEUDO_OPCODES: OpcodeMap = { From fcb96a4ead102b5f2b94901530474e194e41b2df Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Fri, 8 Mar 2024 08:51:07 -0800 Subject: [PATCH 4/9] fix tests --- tests/unit/compiler/test_opcodes.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/unit/compiler/test_opcodes.py b/tests/unit/compiler/test_opcodes.py index 1976d8ba94..7dc0aeaf2c 100644 --- a/tests/unit/compiler/test_opcodes.py +++ b/tests/unit/compiler/test_opcodes.py @@ -38,11 +38,11 @@ def test_version_check(evm_version): assert opcodes.version_check(begin=evm_version) assert opcodes.version_check(end=evm_version) assert opcodes.version_check(begin=evm_version, end=evm_version) - if evm_version not in ("berlin"): - assert not opcodes.version_check(end="berlin") - berlin_check = opcodes.version_check(begin="berlin_check") - assert berlin_check == ( - opcodes.EVM_VERSIONS[evm_version] >= opcodes.EVM_VERSIONS["berlin_check"] + if evm_version not in ("london",): + assert not opcodes.version_check(end="london") + london_check = opcodes.version_check(begin="london") + assert london_check == ( + opcodes.EVM_VERSIONS[evm_version] >= opcodes.EVM_VERSIONS["london"] ) From 458c0981e48267a46769c84f9d313cf0d9ddbcc1 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Fri, 8 Mar 2024 08:55:53 -0800 Subject: [PATCH 5/9] remove berlin from docs and tests --- docs/compiling-a-contract.rst | 10 +++------- tests/unit/cli/vyper_json/test_get_settings.py | 3 ++- tests/unit/compiler/test_pre_parser.py | 4 ++-- vyper/cli/vyper_json.py | 3 ++- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/docs/compiling-a-contract.rst b/docs/compiling-a-contract.rst index 8589955273..ca9d6a2ecf 100644 --- a/docs/compiling-a-contract.rst +++ b/docs/compiling-a-contract.rst @@ -173,14 +173,10 @@ When using the JSON interface, you can include the ``"evmVersion"`` key within t Target Options -------------- -The following is a list of supported EVM versions, and changes in the compiler introduced with each version. Backward compatibility is not guaranteed between each version. +The following is a list of supported EVM versions, and changes in the compiler introduced with each version. Backward compatibility is not guaranteed between each version. In general, there is a soft rule that the compiler will support 3 years of hard fork rulesets, but this policy may be revisited as appropriate. -.. py:attribute:: berlin - - - Gas estimates changed for ``EXTCODESIZE``, ``EXTCODECOPY``, ``EXTCODEHASH``, ``SLOAD``, ``SSTORE``, ``CALL``, ``CALLCODE``, ``DELEGATECALL`` and ``STATICCALL`` - - Functions marked with ``@nonreentrant`` are protected with different values (3 and 2) than contracts targeting pre-berlin. - - ``BASEFEE`` is accessible via ``block.basefee`` +.. py:attribute:: london .. py:attribute:: paris @@ -241,7 +237,7 @@ The following example describes the expected input format of ``vyper-json``. Com }, // Optional "settings": { - "evmVersion": "shanghai", // EVM version to compile for. Can be berlin, london, paris, shanghai (default) or cancun (experimental!). + "evmVersion": "shanghai", // EVM version to compile for. Can be london, paris, shanghai (default) or cancun (experimental!). // optional, optimization mode // defaults to "gas". can be one of "gas", "codesize", "none", // false and true (the last two are for backwards compatibility). diff --git a/tests/unit/cli/vyper_json/test_get_settings.py b/tests/unit/cli/vyper_json/test_get_settings.py index 65ea43456c..a72f526748 100644 --- a/tests/unit/cli/vyper_json/test_get_settings.py +++ b/tests/unit/cli/vyper_json/test_get_settings.py @@ -19,6 +19,7 @@ def test_unknown_evm(): "constantinople", "petersburg", "istanbul", + "berlin", ], ) def test_early_evm(evm_version): @@ -26,6 +27,6 @@ def test_early_evm(evm_version): get_evm_version({"settings": {"evmVersion": evm_version}}) -@pytest.mark.parametrize("evm_version", ["berlin", "london", "paris", "shanghai", "cancun"]) +@pytest.mark.parametrize("evm_version", ["london", "paris", "shanghai", "cancun"]) def test_valid_evm(evm_version): assert evm_version == get_evm_version({"settings": {"evmVersion": evm_version}}) diff --git a/tests/unit/compiler/test_pre_parser.py b/tests/unit/compiler/test_pre_parser.py index 02076ed07e..128b6b16eb 100644 --- a/tests/unit/compiler/test_pre_parser.py +++ b/tests/unit/compiler/test_pre_parser.py @@ -90,10 +90,10 @@ def test(): def test_evm_version_check(assert_compile_failed): code = """ -#pragma evm-version berlin +#pragma evm-version london """ assert compile_code(code, settings=Settings(evm_version=None)) is not None - assert compile_code(code, settings=Settings(evm_version="berlin")) is not None + assert compile_code(code, settings=Settings(evm_version="london")) is not None # should fail if compile options indicate different evm version # from source pragma with pytest.raises(StructureException): diff --git a/vyper/cli/vyper_json.py b/vyper/cli/vyper_json.py index d09b364811..c4f1eddcd8 100755 --- a/vyper/cli/vyper_json.py +++ b/vyper/cli/vyper_json.py @@ -144,8 +144,9 @@ def get_evm_version(input_dict: dict) -> Optional[str]: "byzantium", "constantinople", "istanbul", + "berlin", ): - raise JSONError("Vyper does not support pre-berlin EVM versions") + raise JSONError("Vyper does not support pre-london EVM versions") if evm_version not in EVM_VERSIONS: raise JSONError(f"Unknown EVM version - '{evm_version}'") From 9c1337e274d3faadfdf5eeceffbb92ae5acb69f5 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Fri, 8 Mar 2024 08:57:49 -0800 Subject: [PATCH 6/9] choose different values for net gas metering vs cancun --- vyper/codegen/function_definitions/common.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vyper/codegen/function_definitions/common.py b/vyper/codegen/function_definitions/common.py index d017ba7b81..a130f41565 100644 --- a/vyper/codegen/function_definitions/common.py +++ b/vyper/codegen/function_definitions/common.py @@ -150,14 +150,14 @@ def get_nonreentrant_lock(func_t): LOAD, STORE = "sload", "sstore" if version_check(begin="cancun"): LOAD, STORE = "tload", "tstore" - - if version_check(begin="berlin"): - # any nonzero values would work here (see pricing as of net gas + # for tload/tstore we don't need to care about net gas metering, + # choose small constants (e.g. 0 can be replaced by PUSH0) + final_value, temp_value = 0, 1 + else: + # any nonzero values can work here (see pricing as of net gas # metering); these values are chosen so that downgrading to the # 0,1 scheme (if it is somehow necessary) is safe. final_value, temp_value = 3, 2 - else: - final_value, temp_value = 0, 1 check_notset = ["assert", ["ne", temp_value, [LOAD, nkey]]] From 062a7657f6ba63d9eb10c6c433da244e33db7f36 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Fri, 8 Mar 2024 09:06:39 -0800 Subject: [PATCH 7/9] fix lint --- tests/unit/cli/vyper_json/test_get_settings.py | 2 +- tests/unit/compiler/test_opcodes.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/unit/cli/vyper_json/test_get_settings.py b/tests/unit/cli/vyper_json/test_get_settings.py index a72f526748..975cb9d143 100644 --- a/tests/unit/cli/vyper_json/test_get_settings.py +++ b/tests/unit/cli/vyper_json/test_get_settings.py @@ -19,7 +19,7 @@ def test_unknown_evm(): "constantinople", "petersburg", "istanbul", - "berlin", + "berlin", ], ) def test_early_evm(evm_version): diff --git a/tests/unit/compiler/test_opcodes.py b/tests/unit/compiler/test_opcodes.py index 7dc0aeaf2c..710348a274 100644 --- a/tests/unit/compiler/test_opcodes.py +++ b/tests/unit/compiler/test_opcodes.py @@ -41,9 +41,7 @@ def test_version_check(evm_version): if evm_version not in ("london",): assert not opcodes.version_check(end="london") london_check = opcodes.version_check(begin="london") - assert london_check == ( - opcodes.EVM_VERSIONS[evm_version] >= opcodes.EVM_VERSIONS["london"] - ) + assert london_check == (opcodes.EVM_VERSIONS[evm_version] >= opcodes.EVM_VERSIONS["london"]) def test_get_opcodes(evm_version): From 010a612a966e8790b9d7cce6f76766e8f9c4b3db Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Fri, 8 Mar 2024 09:45:17 -0800 Subject: [PATCH 8/9] update comment --- vyper/evm/opcodes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vyper/evm/opcodes.py b/vyper/evm/opcodes.py index 68821136a7..48edf48f19 100644 --- a/vyper/evm/opcodes.py +++ b/vyper/evm/opcodes.py @@ -8,7 +8,7 @@ # 1. Fork rules go from oldest (lowest value) to newest (highest value). # 2. Fork versions aren't actually tied to anything. They are not a part of our # official API. *DO NOT USE THE VALUES FOR ANYTHING IMPORTANT* besides versioning. -# 3. Per VIP-3365, we support mainnet fork choice rules up to 1 year old +# 3. Per VIP-3365, we support mainnet fork choice rules up to 3 years old # (and may optionally have forward support for experimental/unreleased # fork choice rules) _evm_versions = ("london", "paris", "shanghai", "cancun") From 9197ee54e41e87b8daee2e8f745f3311e0d6f248 Mon Sep 17 00:00:00 2001 From: Charles Cooper Date: Sat, 9 Mar 2024 07:01:25 -0800 Subject: [PATCH 9/9] update wording --- docs/compiling-a-contract.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/compiling-a-contract.rst b/docs/compiling-a-contract.rst index ca9d6a2ecf..c0015c42b9 100644 --- a/docs/compiling-a-contract.rst +++ b/docs/compiling-a-contract.rst @@ -173,7 +173,7 @@ When using the JSON interface, you can include the ``"evmVersion"`` key within t Target Options -------------- -The following is a list of supported EVM versions, and changes in the compiler introduced with each version. Backward compatibility is not guaranteed between each version. In general, there is a soft rule that the compiler will support 3 years of hard fork rulesets, but this policy may be revisited as appropriate. +The following is a list of supported EVM versions, and changes in the compiler introduced with each version. Backward compatibility is not guaranteed between each version. In general, the compiler team maintains an informal policy that the compiler will support 3 years of hard fork rulesets, but this policy may be revisited as appropriate. .. py:attribute:: london