Skip to content

Commit fe74711

Browse files
authored
chore: remove gas estimates from ABI by default (#2590)
gas estimates can break downstream tooling if they are wrong fixes #2151
1 parent 44ec0c9 commit fe74711

File tree

7 files changed

+48
-42
lines changed

7 files changed

+48
-42
lines changed

tests/base_conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def _get_contract(w3, source_code, no_optimize, *args, **kwargs):
109109
interface_codes=kwargs.pop("interface_codes", None),
110110
no_optimize=no_optimize,
111111
evm_version=kwargs.pop("evm_version", None),
112+
show_gas_estimates=True, # Enable gas estimates for testing
112113
)
113114
LARK_GRAMMAR.parse(source_code + "\n") # Test grammar.
114115
abi = out["abi"]

tests/parser/features/test_assert.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import pytest
2-
from eth_abi import decode_single
32
from eth_tester.exceptions import TransactionFailed
43

54

@@ -189,18 +188,12 @@ def test(x: uint256[3]) -> bool:
189188
assert_tx_failed(lambda: c.test([1, 3, 5]))
190189

191190

192-
def test_assert_reason_revert_length(w3, get_contract, memory_mocker):
191+
def test_assert_reason_revert_length(w3, get_contract, assert_tx_failed, memory_mocker):
193192
code = """
194193
@external
195194
def test() -> int128:
196195
assert 1 == 2, "oops"
197196
return 1
198197
"""
199198
c = get_contract(code)
200-
w3.manager.provider.ethereum_tester.backend.is_eip838_error = lambda err: False
201-
with pytest.raises(TransactionFailed) as e_info:
202-
c.test()
203-
error_bytes = eval(_fixup_err_str(e_info.value.args[0]))
204-
assert len(error_bytes) == 100
205-
msg = decode_single("string", error_bytes[36:])
206-
assert msg == "oops"
199+
assert_tx_failed(lambda: c.test(), exc_text="oops")

tests/parser/features/test_assert_unreachable.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import pytest
2-
from eth_tester.exceptions import TransactionFailed
3-
4-
51
def test_assure_refund(w3, get_contract):
62
code = """
73
@external
@@ -32,13 +28,9 @@ def foo(val: int128) -> bool:
3228

3329
assert c.foo(2) is True
3430

35-
assert_tx_failed(lambda: c.foo(1))
36-
assert_tx_failed(lambda: c.foo(-1))
37-
38-
with pytest.raises(TransactionFailed) as e_info:
39-
c.foo(-2)
40-
41-
assert "Invalid opcode 0xfe" in e_info.value.args[0]
31+
assert_tx_failed(lambda: c.foo(1), exc_text="Invalid opcode 0xfe")
32+
assert_tx_failed(lambda: c.foo(-1), exc_text="Invalid opcode 0xfe")
33+
assert_tx_failed(lambda: c.foo(-2), exc_text="Invalid opcode 0xfe")
4234

4335

4436
def test_basic_call_unreachable(w3, get_contract, assert_tx_failed):
@@ -59,6 +51,6 @@ def foo(val: int128) -> int128:
5951

6052
assert c.foo(33) == -123
6153

62-
assert_tx_failed(lambda: c.foo(1))
63-
assert_tx_failed(lambda: c.foo(1))
64-
assert_tx_failed(lambda: c.foo(-1))
54+
assert_tx_failed(lambda: c.foo(1), exc_text="Invalid opcode 0xfe")
55+
assert_tx_failed(lambda: c.foo(1), exc_text="Invalid opcode 0xfe")
56+
assert_tx_failed(lambda: c.foo(-1), exc_text="Invalid opcode 0xfe")

vyper/cli/vyper_compile.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import vyper
1111
from vyper.cli import vyper_json
1212
from vyper.cli.utils import extract_file_interface_imports, get_interface_file_path
13-
from vyper.codegen.lll_node import LLLnode
1413
from vyper.compiler.settings import VYPER_TRACEBACK_LIMIT
1514
from vyper.evm.opcodes import DEFAULT_EVM_VERSION, EVM_VERSIONS
1615
from vyper.typing import ContractCodes, ContractPath, OutputFormats
@@ -91,7 +90,7 @@ def _parse_args(argv):
9190
)
9291
parser.add_argument(
9392
"--show-gas-estimates",
94-
help="Show gas estimates in ir output mode.",
93+
help="Show gas estimates in abi and ir output mode.",
9594
action="store_true",
9695
)
9796
parser.add_argument(
@@ -230,9 +229,6 @@ def compile_files(
230229
no_optimize: bool = False,
231230
) -> OrderedDict:
232231

233-
if show_gas_estimates:
234-
LLLnode.repr_show_gas = True
235-
236232
root_path = Path(root_folder).resolve()
237233
if not root_path.exists():
238234
raise FileNotFoundError(f"Invalid root path - '{root_path.as_posix()}' does not exist")
@@ -266,6 +262,7 @@ def compile_files(
266262
interface_codes=get_interface_codes(root_path, contract_sources),
267263
evm_version=evm_version,
268264
no_optimize=no_optimize,
265+
show_gas_estimates=show_gas_estimates,
269266
)
270267
if show_version:
271268
compiler_data["version"] = vyper.__version__

vyper/compiler/__init__.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def compile_codes(
3939
interface_codes: Union[InterfaceDict, InterfaceImports, None] = None,
4040
initial_id: int = 0,
4141
no_optimize: bool = False,
42+
show_gas_estimates: bool = False,
4243
) -> OrderedDict:
4344
"""
4445
Generate compiler output(s) from one or more contract source codes.
@@ -60,6 +61,8 @@ def compile_codes(
6061
implemented ruleset.
6162
no_optimize: bool, optional
6263
Turn off optimizations. Defaults to False
64+
show_gas_estimates: bool, optional
65+
Show gas estimates for abi and ir output modes
6366
interface_codes: Dict, optional
6467
Interfaces that may be imported by the contracts during compilation.
6568
@@ -93,7 +96,14 @@ def compile_codes(
9396
):
9497
interfaces = interfaces[contract_name]
9598

96-
compiler_data = CompilerData(source_code, contract_name, interfaces, source_id, no_optimize)
99+
compiler_data = CompilerData(
100+
source_code,
101+
contract_name,
102+
interfaces,
103+
source_id,
104+
no_optimize,
105+
show_gas_estimates
106+
)
97107
for output_format in output_formats[contract_name]:
98108
if output_format not in OUTPUT_FORMATS:
99109
raise ValueError(f"Unsupported format type {repr(output_format)}")
@@ -118,6 +128,7 @@ def compile_code(
118128
interface_codes: Optional[InterfaceImports] = None,
119129
evm_version: str = DEFAULT_EVM_VERSION,
120130
no_optimize: bool = False,
131+
show_gas_estimates: bool = False,
121132
) -> dict:
122133
"""
123134
Generate compiler output(s) from a single contract source code.
@@ -134,6 +145,8 @@ def compile_code(
134145
implemented ruleset.
135146
no_optimize: bool, optional
136147
Turn off optimizations. Defaults to False
148+
show_gas_estimates: bool, optional
149+
Show gas estimates for abi and ir output modes
137150
interface_codes: Dict, optional
138151
Interfaces that may be imported by the contracts during compilation.
139152
@@ -154,4 +167,5 @@ def compile_code(
154167
interface_codes=interface_codes,
155168
evm_version=evm_version,
156169
no_optimize=no_optimize,
170+
show_gas_estimates=show_gas_estimates,
157171
)[UNKNOWN_CONTRACT_NAME]

vyper/compiler/output.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ def build_interface_output(compiler_data: CompilerData) -> str:
7474

7575

7676
def build_ir_output(compiler_data: CompilerData) -> LLLnode:
77+
if compiler_data.show_gas_estimates:
78+
LLLnode.repr_show_gas = True
7779
return compiler_data.lll_nodes
7880

7981

@@ -98,20 +100,21 @@ def build_method_identifiers_output(compiler_data: CompilerData) -> dict:
98100

99101
def build_abi_output(compiler_data: CompilerData) -> list:
100102
abi = compiler_data.vyper_module_folded._metadata["type"].to_abi_dict()
101-
# Add gas estimates for each function to ABI
102-
gas_estimates = build_gas_estimates(compiler_data.lll_runtime)
103-
for func in abi:
104-
try:
105-
func_signature = func["name"]
106-
except KeyError:
107-
# constructor and fallback functions don't have a name
108-
continue
103+
if compiler_data.show_gas_estimates:
104+
# Add gas estimates for each function to ABI
105+
gas_estimates = build_gas_estimates(compiler_data.lll_runtime)
106+
for func in abi:
107+
try:
108+
func_signature = func["name"]
109+
except KeyError:
110+
# constructor and fallback functions don't have a name
111+
continue
109112

110-
func_name, _, _ = func_signature.partition("(")
111-
# This check ensures we skip __init__ since it has no estimate
112-
if func_name in gas_estimates:
113-
# TODO: mutation
114-
func["gas"] = gas_estimates[func_name]
113+
func_name, _, _ = func_signature.partition("(")
114+
# This check ensures we skip __init__ since it has no estimate
115+
if func_name in gas_estimates:
116+
# TODO: mutation
117+
func["gas"] = gas_estimates[func_name]
115118
return abi
116119

117120

vyper/compiler/phases.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def __init__(
4848
interface_codes: Optional[InterfaceImports] = None,
4949
source_id: int = 0,
5050
no_optimize: bool = False,
51+
show_gas_estimates: bool = False,
5152
) -> None:
5253
"""
5354
Initialization method.
@@ -64,12 +65,17 @@ def __init__(
6465
* JSON interfaces are given as lists, vyper interfaces as strings
6566
source_id : int, optional
6667
ID number used to identify this contract in the source map.
68+
no_optimize: bool, optional
69+
Turn off optimizations. Defaults to False
70+
show_gas_estimates: bool, optional
71+
Show gas estimates for abi and ir output modes
6772
"""
6873
self.contract_name = contract_name
6974
self.source_code = source_code
7075
self.interface_codes = interface_codes
7176
self.source_id = source_id
7277
self.no_optimize = no_optimize
78+
self.show_gas_estimates = show_gas_estimates
7379

7480
@property
7581
def vyper_module(self) -> vy_ast.Module:

0 commit comments

Comments
 (0)