def analyze_contracts(self): # pylint: disable=too-many-statements,too-many-branches if not self._parsed: raise SlitherException("Parse the contract before running analyses") self._convert_to_slithir() compute_dependency(self._core) self._core.compute_storage_layout() self._analyzed = True
def analyze_contracts(self): # pylint: disable=too-many-statements,too-many-branches if not self._underlying_contract_to_parser: logger.info( f"No contract were found in {self._core.filename}, check the correct compilation" ) if self._analyzed: raise Exception("Contract analysis can be run only once!") # First we save all the contracts in a dict # the key is the contractid for contract in self._underlying_contract_to_parser: if (contract.name.startswith("SlitherInternalTopLevelContract") and not contract.is_top_level): raise SlitherException( """Your codebase has a contract named 'SlitherInternalTopLevelContract'. Please rename it, this name is reserved for Slither's internals""") if contract.name in self._core.contracts_as_dict: if contract.id != self._core.contracts_as_dict[ contract.name].id: self._core.contract_name_collisions[contract.name].append( contract.source_mapping_str) self._core.contract_name_collisions[contract.name].append( self._core.contracts_as_dict[ contract.name].source_mapping_str) else: self._contracts_by_id[contract.id] = contract self._core.contracts_as_dict[contract.name] = contract # Update of the inheritance for contract_parser in self._underlying_contract_to_parser.values(): # remove the first elem in linearizedBaseContracts as it is the contract itself ancestors = [] fathers = [] father_constructors = [] # try: # Resolve linearized base contracts. missing_inheritance = False for i in contract_parser.linearized_base_contracts[1:]: if i in contract_parser.remapping: ancestors.append( self._core.get_contract_from_name( contract_parser.remapping[i])) elif i in self._contracts_by_id: ancestors.append(self._contracts_by_id[i]) else: missing_inheritance = True # Resolve immediate base contracts for i in contract_parser.baseContracts: if i in contract_parser.remapping: fathers.append( self._core.get_contract_from_name( contract_parser.remapping[i])) elif i in self._contracts_by_id: fathers.append(self._contracts_by_id[i]) else: missing_inheritance = True # Resolve immediate base constructor calls for i in contract_parser.baseConstructorContractsCalled: if i in contract_parser.remapping: father_constructors.append( self._core.get_contract_from_name( contract_parser.remapping[i])) elif i in self._contracts_by_id: father_constructors.append(self._contracts_by_id[i]) else: missing_inheritance = True contract_parser.underlying_contract.set_inheritance( ancestors, fathers, father_constructors) if missing_inheritance: self._core.contracts_with_missing_inheritance.add( contract_parser.underlying_contract) contract_parser.log_incorrect_parsing( f"Missing inheritance {contract_parser}") contract_parser.set_is_analyzed(True) contract_parser.delete_content() contracts_to_be_analyzed = list( self._underlying_contract_to_parser.values()) # Any contract can refer another contract enum without need for inheritance self._analyze_all_enums(contracts_to_be_analyzed) # pylint: disable=expression-not-assigned [ c.set_is_analyzed(False) for c in self._underlying_contract_to_parser.values() ] libraries = [ c for c in contracts_to_be_analyzed if c.underlying_contract.contract_kind == "library" ] contracts_to_be_analyzed = [ c for c in contracts_to_be_analyzed if c.underlying_contract.contract_kind != "library" ] # We first parse the struct/variables/functions/contract self._analyze_first_part(contracts_to_be_analyzed, libraries) # pylint: disable=expression-not-assigned [ c.set_is_analyzed(False) for c in self._underlying_contract_to_parser.values() ] # We analyze the struct and parse and analyze the events # A contract can refer in the variables a struct or a event from any contract # (without inheritance link) self._analyze_second_part(contracts_to_be_analyzed, libraries) [ c.set_is_analyzed(False) for c in self._underlying_contract_to_parser.values() ] # Then we analyse state variables, functions and modifiers self._analyze_third_part(contracts_to_be_analyzed, libraries) self._analyzed = True self._convert_to_slithir() compute_dependency(self._core) self._core.compute_storage_layout()
def _analyze_contracts(self): if not self._contractsNotParsed: logger.info(f'No contract were found in {self.filename}, check the correct compilation') if self._analyzed: raise Exception('Contract analysis can be run only once!') # First we save all the contracts in a dict # the key is the contractid for contract in self._contractsNotParsed: if contract.name in self._contracts: if contract.id != self._contracts[contract.name].id: info = 'Slither does not handle projects with contract names re-use' info += '\n{} is defined in:'.format(contract.name) info += '\n- {}\n- {}'.format(contract.source_mapping_str, self._contracts[contract.name].source_mapping_str) logger.error(info) exit(-1) else: self._contracts_by_id[contract.id] = contract self._contracts[contract.name] = contract # Update of the inheritance for contract in self._contractsNotParsed: # remove the first elem in linearizedBaseContracts as it is the contract itself ancestors = [] fathers = [] father_constructors = [] try: # Resolve linearized base contracts. for i in contract.linearizedBaseContracts[1:]: if i in contract.remapping: ancestors.append(self.get_contract_from_name(contract.remapping[i])) else: ancestors.append(self._contracts_by_id[i]) # Resolve immediate base contracts for i in contract.baseContracts: if i in contract.remapping: fathers.append(self.get_contract_from_name(contract.remapping[i])) else: fathers.append(self._contracts_by_id[i]) # Resolve immediate base constructor calls for i in contract.baseConstructorContractsCalled: if i in contract.remapping: father_constructors.append(self.get_contract_from_name(contract.remapping[i])) else: father_constructors.append(self._contracts_by_id[i]) except KeyError: logger.error(red('A contract was not found, it is likely that your codebase contains muliple contracts with the same name')) logger.error(red('Truffle does not handle this case during compilation')) logger.error(red('Please read https://github.com/trailofbits/slither/wiki#keyerror-or-nonetype-error')) logger.error(red('And update your code to remove the duplicate')) exit(-1) contract.setInheritance(ancestors, fathers, father_constructors) contracts_to_be_analyzed = self.contracts # Any contract can refer another contract enum without need for inheritance self._analyze_all_enums(contracts_to_be_analyzed) [c.set_is_analyzed(False) for c in self.contracts] libraries = [c for c in contracts_to_be_analyzed if c.contract_kind == 'library'] contracts_to_be_analyzed = [c for c in contracts_to_be_analyzed if c.contract_kind != 'library'] # We first parse the struct/variables/functions/contract self._analyze_first_part(contracts_to_be_analyzed, libraries) [c.set_is_analyzed(False) for c in self.contracts] # We analyze the struct and parse and analyze the events # A contract can refer in the variables a struct or a event from any contract # (without inheritance link) self._analyze_second_part(contracts_to_be_analyzed, libraries) [c.set_is_analyzed(False) for c in self.contracts] # Then we analyse state variables, functions and modifiers self._analyze_third_part(contracts_to_be_analyzed, libraries) self._analyzed = True self._convert_to_slithir() compute_dependency(self)
def _analyze_contracts(self): if not self._contractsNotParsed: logger.info( f'No contract were found in {self.filename}, check the correct compilation' ) if self._analyzed: raise Exception('Contract analysis can be run only once!') # First we save all the contracts in a dict # the key is the contractid for contract in self._contractsNotParsed: if contract.name in self._contracts: if contract.id != self._contracts[contract.name].id: self._contract_name_collisions[contract.name].append( contract.source_mapping_str) self._contract_name_collisions[contract.name].append( self._contracts[contract.name].source_mapping_str) else: self._contracts_by_id[contract.id] = contract self._contracts[contract.name] = contract # Update of the inheritance for contract in self._contractsNotParsed: # remove the first elem in linearizedBaseContracts as it is the contract itself ancestors = [] fathers = [] father_constructors = [] # try: # Resolve linearized base contracts. missing_inheritance = False for i in contract.linearizedBaseContracts[1:]: if i in contract.remapping: ancestors.append( self.get_contract_from_name(contract.remapping[i])) elif i in self._contracts_by_id: ancestors.append(self._contracts_by_id[i]) else: missing_inheritance = True # Resolve immediate base contracts for i in contract.baseContracts: if i in contract.remapping: fathers.append( self.get_contract_from_name(contract.remapping[i])) elif i in self._contracts_by_id: fathers.append(self._contracts_by_id[i]) else: missing_inheritance = True # Resolve immediate base constructor calls for i in contract.baseConstructorContractsCalled: if i in contract.remapping: father_constructors.append( self.get_contract_from_name(contract.remapping[i])) elif i in self._contracts_by_id: father_constructors.append(self._contracts_by_id[i]) else: missing_inheritance = True contract.setInheritance(ancestors, fathers, father_constructors) if missing_inheritance: self._contract_with_missing_inheritance.add(contract) contract.log_incorrect_parsing( f'Missing inheritance {contract}') contract.set_is_analyzed(True) contract.delete_content() contracts_to_be_analyzed = self.contracts # Any contract can refer another contract enum without need for inheritance self._analyze_all_enums(contracts_to_be_analyzed) [c.set_is_analyzed(False) for c in self.contracts] libraries = [ c for c in contracts_to_be_analyzed if c.contract_kind == 'library' ] contracts_to_be_analyzed = [ c for c in contracts_to_be_analyzed if c.contract_kind != 'library' ] # We first parse the struct/variables/functions/contract self._analyze_first_part(contracts_to_be_analyzed, libraries) [c.set_is_analyzed(False) for c in self.contracts] # We analyze the struct and parse and analyze the events # A contract can refer in the variables a struct or a event from any contract # (without inheritance link) self._analyze_second_part(contracts_to_be_analyzed, libraries) [c.set_is_analyzed(False) for c in self.contracts] # Then we analyse state variables, functions and modifiers self._analyze_third_part(contracts_to_be_analyzed, libraries) self._analyzed = True self._convert_to_slithir() compute_dependency(self)