def _getRootNode(self, contractAddr: str, versionString: str) -> solcast.nodes.NodeBase: solc_input_json_str = self.solc_input_json_str_skeleton % ( contractAddr, self.contract_src_path_skeleton % (contractAddr)) input_json = json.loads(solc_input_json_str) # TODO: calculate the most suitable complier version self._setMostSuitableVersion(versionString) output_json = solcx.compile_standard(input_json, allow_paths=self.allow_paths) # print(self.allow_paths) nodes: List[ solcast.nodes.IterableNodeBase] = solcast.from_standard_output( output_json) return nodes[0]
def _get_nodes(output_json: Dict) -> Tuple[Dict, Dict, Dict]: source_nodes = solcast.from_standard_output(output_json) stmt_nodes = _get_statement_nodes(source_nodes) branch_nodes = _get_branch_nodes(source_nodes) return source_nodes, stmt_nodes, branch_nodes
def generate_build_json(input_json, output_json, compiler_data={}, silent=True): '''Formats standard compiler output to the brownie build json. Args: input_json: solc input json used to compile output_json: output json returned by compiler compiler_data: additonal data to include under 'compiler' in build json silent: verbose reporting Returns: build json dict''' if not silent: print("Generating build data...") compiler_data.update({ "optimize": input_json['settings']['optimizer']['enabled'], "runs": input_json['settings']['optimizer']['runs'] }) minify = 'minify_source' in compiler_data and compiler_data['minify_source'] build_json = {} path_list = list(input_json['sources']) source_nodes = solcast.from_standard_output(deepcopy(output_json)) statement_nodes = get_statement_nodes(source_nodes) branch_nodes = get_branch_nodes(source_nodes) for path, contract_name in [(k, v) for k in path_list for v in output_json['contracts'][k]]: if not silent: print(f" - {contract_name}...") evm = output_json['contracts'][path][contract_name]['evm'] node = next(i[contract_name] for i in source_nodes if i.name == path) bytecode = format_link_references(evm) paths = sorted( set([node.parent().path] + [i.parent().path for i in node.dependencies])) pc_map, statement_map, branch_map = generate_coverage_data( evm['deployedBytecode']['sourceMap'], evm['deployedBytecode']['opcodes'], node, statement_nodes, branch_nodes) build_json[contract_name] = { 'abi': output_json['contracts'][path][contract_name]['abi'], 'allSourcePaths': paths, 'ast': output_json['sources'][path]['ast'], 'bytecode': bytecode, 'bytecodeSha1': get_bytecode_hash(bytecode), 'compiler': compiler_data, 'contractName': contract_name, 'coverageMap': { 'statements': statement_map, 'branches': branch_map }, 'deployedBytecode': evm['deployedBytecode']['object'], 'deployedSourceMap': evm['deployedBytecode']['sourceMap'], 'dependencies': [i.name for i in node.dependencies], # 'networks': {}, 'offset': node.offset, 'opcodes': evm['deployedBytecode']['opcodes'], 'pcMap': pc_map, 'sha1': sources.get_hash(contract_name, minify), 'source': input_json['sources'][path]['content'], 'sourceMap': evm['bytecode']['sourceMap'], 'sourcePath': path, 'type': node.type } return build_json
def get_abi( contract_sources: Dict[str, str], allow_paths: Optional[str] = None, remappings: Optional[list] = None, silent: bool = True, ) -> Dict: """ Generate ABIs from contract interfaces. Arguments --------- contract_sources : dict a dictionary in the form of {'path': "source code"} allow_paths : str, optional Compiler allowed filesystem import path remappings : list, optional List of solidity path remappings silent : bool, optional Disable verbose reporting Returns ------- dict Compiled ABIs in the format `{'contractName': [ABI]}` """ final_output = { Path(k).stem: { "abi": json.loads(v), "contractName": Path(k).stem, "type": "interface", "source": None, "offset": None, "sha1": sha1(v.encode()).hexdigest(), } for k, v in contract_sources.items() if Path(k).suffix == ".json" } for path, source in [(k, v) for k, v in contract_sources.items() if Path(k).suffix == ".vy"]: input_json = generate_input_json({path: source}, language="Vyper") input_json["settings"]["outputSelection"]["*"] = {"*": ["abi"]} try: output_json = compile_from_input_json(input_json, silent, allow_paths) except Exception: # vyper interfaces do not convert to ABIs # https://github.com/vyperlang/vyper/issues/1944 continue name = Path(path).stem final_output[name] = { "abi": output_json["contracts"][path][name]["abi"], "contractName": name, "type": "interface", "source": source, "offset": [0, len(source)], "sha1": sha1(contract_sources[path].encode()).hexdigest(), } solc_sources = { k: v for k, v in contract_sources.items() if Path(k).suffix == ".sol" } if not solc_sources: return final_output compiler_targets = find_solc_versions(solc_sources, install_needed=True, silent=silent) for version, path_list in compiler_targets.items(): to_compile = { k: v for k, v in contract_sources.items() if k in path_list } set_solc_version(version) input_json = generate_input_json(to_compile, language="Solidity", remappings=remappings) input_json["settings"]["outputSelection"]["*"] = { "*": ["abi"], "": ["ast"] } output_json = compile_from_input_json(input_json, silent, allow_paths) source_nodes = solcast.from_standard_output(output_json) abi_json = { k: v for k, v in output_json["contracts"].items() if k in path_list } for path, name, data in [(k, x, y) for k, v in abi_json.items() for x, y in v.items()]: contract_node = next(i[name] for i in source_nodes if i.absolutePath == path) dependencies = [] for node in [ i for i in contract_node.dependencies if i.nodeType == "ContractDefinition" ]: dependency_name = node.name path_str = node.parent().absolutePath dependencies.append(_get_alias(dependency_name, path_str)) final_output[name] = { "abi": data["abi"], "ast": output_json["sources"][path]["ast"], "contractName": name, "dependencies": dependencies, "type": "interface", "source": contract_sources[path], "offset": contract_node.offset, "sha1": sha1(contract_sources[path].encode()).hexdigest(), } return final_output
def generate_build_json(input_json: Dict, output_json: Dict, compiler_data: Optional[Dict] = None, silent: bool = True) -> Dict: """Formats standard compiler output to the brownie build json. Args: input_json: solc input json used to compile output_json: output json returned by compiler compiler_data: additonal data to include under 'compiler' in build json silent: verbose reporting Returns: build json dict""" if not silent: print("Generating build data...") if compiler_data is None: compiler_data = {} compiler_data.update({ "optimize": input_json["settings"]["optimizer"]["enabled"], "runs": input_json["settings"]["optimizer"]["runs"], "evm_version": input_json["settings"]["evmVersion"], }) minified = "minify_source" in compiler_data and compiler_data[ "minify_source"] build_json = {} path_list = list(input_json["sources"]) source_nodes = solcast.from_standard_output(deepcopy(output_json)) statement_nodes = _get_statement_nodes(source_nodes) branch_nodes = _get_branch_nodes(source_nodes) for path, contract_name in [(k, v) for k in path_list for v in output_json["contracts"][k]]: if not silent: print(f" - {contract_name}...") abi = output_json["contracts"][path][contract_name]["abi"] evm = output_json["contracts"][path][contract_name]["evm"] bytecode = _format_link_references(evm) hash_ = sources.get_hash(input_json["sources"][path]["content"], contract_name, minified) node = next(i[contract_name] for i in source_nodes if i.absolutePath == path) paths = sorted( set([node.parent().absolutePath] + [i.parent().absolutePath for i in node.dependencies])) pc_map, statement_map, branch_map = _generate_coverage_data( evm["deployedBytecode"]["sourceMap"], evm["deployedBytecode"]["opcodes"], node, statement_nodes, branch_nodes, next((True for i in abi if i["type"] == "fallback"), False), ) build_json[contract_name] = { "abi": abi, "allSourcePaths": paths, "ast": output_json["sources"][path]["ast"], "bytecode": bytecode, "bytecodeSha1": _get_bytecode_hash(bytecode), "compiler": compiler_data, "contractName": contract_name, "coverageMap": { "statements": statement_map, "branches": branch_map }, "deployedBytecode": evm["deployedBytecode"]["object"], "deployedSourceMap": evm["deployedBytecode"]["sourceMap"], "dependencies": [i.name for i in node.dependencies], # 'networks': {}, "offset": node.offset, "opcodes": evm["deployedBytecode"]["opcodes"], "pcMap": pc_map, "sha1": hash_, "source": input_json["sources"][path]["content"], "sourceMap": evm["bytecode"]["sourceMap"], "sourcePath": path, "type": node.contractKind, } if not silent: print("") return build_json
def test_mutation(path): with open(path) as fp: output_json = json.load(fp) original = deepcopy(output_json) solcast.from_standard_output(output_json) assert original == output_json