def _verify_contract_integrity(self, address: Union[bytes, str], sol_filename: str, *, libraries: Dict = None, contract_name: str = None, is_library: bool = False, cwd=None) -> Any: if isinstance(address, bytes): address = self.w3.toChecksumAddress(address) if contract_name is None: contract_name = get_contract_names(sol_filename)[0] actual_byte_code = self.__normalized_hex(self.w3.eth.getCode(address)) if not actual_byte_code: raise IntegrityError(f'Expected contract {contract_name} is not deployed at address {address}') cout = self.compile_contract(sol_filename, contract_name, libs=libraries, cwd=cwd) expected_byte_code = self.__normalized_hex(cout['deployed_bin']) if is_library: # https://github.com/ethereum/solidity/issues/7101 expected_byte_code = expected_byte_code[:2] + self.__normalized_hex(address) + expected_byte_code[42:] if actual_byte_code != expected_byte_code: raise IntegrityError(f'Deployed contract at address {address} does not match local contract {sol_filename}') zk_print(f'Contract@{address} matches {sol_filename[sol_filename.rfind("/") + 1:]}:{contract_name}') return self.w3.eth.contract( address=address, abi=cout['abi'] )
def _verify_library_integrity(self, libraries: List[Tuple[str, str]], contract_with_libs_addr: str, sol_with_libs_filename: str) -> Dict[str, str]: cname = get_contract_names(sol_with_libs_filename)[0] actual_code = self.__normalized_hex(self.w3.eth.getCode(contract_with_libs_addr)) if not actual_code: raise IntegrityError(f'Expected contract {cname} is not deployed at address {contract_with_libs_addr}') code_with_placeholders = self.__normalized_hex(self.compile_contract(sol_with_libs_filename, cname)['deployed_bin']) if len(actual_code) != len(code_with_placeholders): raise IntegrityError(f'Local code of contract {cname} has different length than remote contract') addresses = {} for lib_name, lib_sol in libraries: # Compute placeholder according to # https://solidity.readthedocs.io/en/v0.5.13/using-the-compiler.html#using-the-commandline-compiler hash = self.w3.solidityKeccak(['string'], [f'{lib_sol[lib_sol.rfind("/") + 1:]}:{lib_name}']) placeholder = f'__${self.__normalized_hex(hash)[:34]}$__' # Retrieve concrete address in deployed code at placeholder offset in local code and verify library contract integrity lib_address_offset = code_with_placeholders.find(placeholder) if lib_address_offset != -1: lib_address = self.w3.toChecksumAddress(actual_code[lib_address_offset:lib_address_offset+40]) with cfg.library_compilation_environment(): self._verify_contract_integrity(lib_address, lib_sol, contract_name=lib_name, is_library=True) addresses[lib_name] = lib_address return addresses
def deploy_solidity_contract(self, sol_filename: str, contract_name: Optional[str], sender: Union[bytes, str]) -> str: contract_name = get_contract_names( sol_filename)[0] if contract_name is None else contract_name contract = self._deploy_contract( sender, self.compile_contract(sol_filename, contract_name)) return str(contract.address)
def name(self): names = get_contract_names(self.file_location) assert len(names) == 1 return names[0]