def test_struct_abi(): code = """ struct MyStruct: a: address b: uint256 @external @view def foo(s: MyStruct) -> MyStruct: return s """ data = CompilerData(code) abi = build_abi_output(data) func_abi = abi[0] assert func_abi["name"] == "foo" expected_output = [ { "type": "tuple", "name": "", "components": [{"type": "address", "name": "a"}, {"type": "uint256", "name": "b"}], } ] assert func_abi["outputs"] == expected_output expected_input = { "type": "tuple", "name": "s", "components": [{"type": "address", "name": "a"}, {"type": "uint256", "name": "b"}], } assert func_abi["inputs"][0] == expected_input
def test_struct_abi(): code = """ struct MyStruct: a: address b: uint256 @public @constant def foo(s: MyStruct) -> MyStruct: return s """ data = CompilerData(code) abi = build_abi_output(data) func_abi = abi[0] assert func_abi["name"] == "foo" expected = { 'type': 'tuple', 'name': '', 'components': [{ 'type': 'address', 'name': 'a' }, { 'type': 'uint256', 'name': 'b' }] } assert func_abi["outputs"][0] == expected expected['name'] = "s" assert func_abi["inputs"][0] == expected
def test_only_init_function(source_code): empty_sig = [ {"outputs": [], "inputs": [], "stateMutability": "nonpayable", "type": "constructor"} ] data = CompilerData(source_code) assert build_abi_output(data) == empty_sig
def test_default_abi(): default_code = """ @payable @external def __default__(): pass """ data = CompilerData(default_code) assert build_abi_output(data) == [{"stateMutability": "payable", "type": "fallback"}]
def test_only_init_function(source_code): empty_sig = [{ 'outputs': [], 'inputs': [], 'constant': False, 'payable': False, 'type': 'constructor' }] data = CompilerData(source_code) assert build_abi_output(data) == empty_sig
def test_default_abi(): default_code = """ @payable @public def __default__(): pass """ data = CompilerData(default_code) assert build_abi_output(data) == [{ 'constant': False, 'payable': True, 'type': 'fallback' }]
def compile_codes( contract_sources: ContractCodes, output_formats: Union[OutputDict, OutputFormats, None] = None, exc_handler: Union[Callable, None] = None, interface_codes: Union[InterfaceDict, InterfaceImports, None] = None, initial_id: int = 0, ) -> OrderedDict: """ Generate compiler output(s) from one or more contract source codes. Arguments --------- contract_sources: Dict[str, str] Vyper source codes to be compiled. Formatted as `{"contract name": "source code"}` output_formats: List, optional List of compiler outputs to generate. Possible options are all the keys in `OUTPUT_FORMATS`. If not given, the deployment bytecode is generated. exc_handler: Callable, optional Callable used to handle exceptions if the compilation fails. Should accept two arguments - the name of the contract, and the exception that was raised initial_id: int, optional The lowest source ID value to be used when generating the source map. evm_version: str, optional The target EVM ruleset to compile for. If not given, defaults to the latest implemented ruleset. interface_codes: Dict, optional Interfaces that may be imported by the contracts during compilation. * May be a singular dictionary shared across all sources to be compiled, i.e. `{'interface name': "definition"}` * or may be organized according to contracts that are being compiled, i.e. `{'contract name': {'interface name': "definition"}` * Interface definitions are formatted as: `{'type': "json/vyper", 'code': "interface code"}` * JSON interfaces are given as lists, vyper interfaces as strings Returns ------- Dict Compiler output as `{'contract name': {'output key': "output data"}}` """ if output_formats is None: output_formats = ("bytecode", ) if isinstance(output_formats, Sequence): output_formats = dict( (k, output_formats) for k in contract_sources.keys()) out: OrderedDict = OrderedDict() for source_id, contract_name in enumerate(sorted(contract_sources), start=initial_id): # trailing newline fixes python parsing bug when source ends in a comment # https://bugs.python.org/issue35107 source_code = f"{contract_sources[contract_name]}\n" interfaces: Any = interface_codes if (isinstance(interfaces, dict) and contract_name in interfaces and isinstance(interfaces[contract_name], dict)): interfaces = interfaces[contract_name] compiler_data = CompilerData(source_code, contract_name, interfaces, source_id) for output_format in output_formats[contract_name]: if output_format not in OUTPUT_FORMATS: raise ValueError( f"Unsupported format type {repr(output_format)}") try: out.setdefault(contract_name, {}) out[contract_name][output_format] = OUTPUT_FORMATS[ output_format](compiler_data) except Exception as exc: if exc_handler is not None: exc_handler(contract_name, exc) else: raise exc return out
def parse_natspec(code): vyper_ast = CompilerData(code).vyper_module_folded return vy_ast.parse_natspec(vyper_ast)
def compile_codes( contract_sources: ContractCodes, output_formats: Union[OutputDict, OutputFormats, None] = None, exc_handler: Union[Callable, None] = None, interface_codes: Union[InterfaceDict, InterfaceImports, None] = None, initial_id: int = 0, no_optimize: bool = False, storage_layouts: Dict[ContractPath, StorageLayout] = None, show_gas_estimates: bool = False, ) -> OrderedDict: """ Generate compiler output(s) from one or more contract source codes. Arguments --------- contract_sources: Dict[str, str] Vyper source codes to be compiled. Formatted as `{"contract name": "source code"}` output_formats: List, optional List of compiler outputs to generate. Possible options are all the keys in `OUTPUT_FORMATS`. If not given, the deployment bytecode is generated. exc_handler: Callable, optional Callable used to handle exceptions if the compilation fails. Should accept two arguments - the name of the contract, and the exception that was raised initial_id: int, optional The lowest source ID value to be used when generating the source map. evm_version: str, optional The target EVM ruleset to compile for. If not given, defaults to the latest implemented ruleset. no_optimize: bool, optional Turn off optimizations. Defaults to False show_gas_estimates: bool, optional Show gas estimates for abi and ir output modes interface_codes: Dict, optional Interfaces that may be imported by the contracts during compilation. * May be a singular dictionary shared across all sources to be compiled, i.e. `{'interface name': "definition"}` * or may be organized according to contracts that are being compiled, i.e. `{'contract name': {'interface name': "definition"}` * Interface definitions are formatted as: `{'type': "json/vyper", 'code': "interface code"}` * JSON interfaces are given as lists, vyper interfaces as strings Returns ------- Dict Compiler output as `{'contract name': {'output key': "output data"}}` """ if output_formats is None: output_formats = ("bytecode", ) if isinstance(output_formats, Sequence): output_formats = dict( (k, output_formats) for k in contract_sources.keys()) out: OrderedDict = OrderedDict() for source_id, contract_name in enumerate(sorted(contract_sources), start=initial_id): source_code = contract_sources[contract_name] interfaces: Any = interface_codes storage_layout_override = None if storage_layouts and contract_name in storage_layouts: storage_layout_override = storage_layouts[contract_name] if (isinstance(interfaces, dict) and contract_name in interfaces and isinstance(interfaces[contract_name], dict)): interfaces = interfaces[contract_name] # make IR output the same between runs codegen.reset_names() compiler_data = CompilerData( source_code, contract_name, interfaces, source_id, no_optimize, storage_layout_override, show_gas_estimates, ) for output_format in output_formats[contract_name]: if output_format not in OUTPUT_FORMATS: raise ValueError( f"Unsupported format type {repr(output_format)}") try: out.setdefault(contract_name, {}) out[contract_name][output_format] = OUTPUT_FORMATS[ output_format](compiler_data) except Exception as exc: if exc_handler is not None: exc_handler(contract_name, exc) else: raise exc return out