Beispiel #1
0
    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
Beispiel #2
0
    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()
Beispiel #3
0
    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)
Beispiel #4
0
    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)