pull/1022/head
Tadashi 3 years ago
parent 8ee4150def
commit b6103dd015
  1. 22
      slither/detectors/functions/external_function.py
  2. 8
      tests/test_detectors.py

@ -25,9 +25,7 @@ class ExternalFunction(AbstractDetector):
WIKI_TITLE = "Public function that could be declared external" WIKI_TITLE = "Public function that could be declared external"
WIKI_DESCRIPTION = "`public` functions that are never called by the contract should be declared `external`, and its immutable parameters should be located in `calldata` to save gas." WIKI_DESCRIPTION = "`public` functions that are never called by the contract should be declared `external`, and its immutable parameters should be located in `calldata` to save gas."
WIKI_RECOMMENDATION = ( WIKI_RECOMMENDATION = "Use the `external` attribute for functions never called from the contract, and change the location of immutable parameters to `calldata` to save gas."
"Use the `external` attribute for functions never called from the contract, and change the location of immutable parameters to `calldata` to save gas."
)
@staticmethod @staticmethod
def detect_functions_called(contract): def detect_functions_called(contract):
@ -112,10 +110,12 @@ class ExternalFunction(AbstractDetector):
@staticmethod @staticmethod
def is_reference_type(parameter): def is_reference_type(parameter):
if isinstance(parameter.type, ArrayType): if isinstance(parameter.type, ArrayType):
return True return True
if isinstance(parameter.type, MappingType): if isinstance(parameter.type, MappingType):
return True return True
if isinstance(parameter.type, UserDefinedType) and isinstance(parameter.type.type, Structure): if isinstance(parameter.type, UserDefinedType) and isinstance(
parameter.type.type, Structure
):
return True return True
if str(parameter.type) in ["bytes", "string"]: if str(parameter.type) in ["bytes", "string"]:
return True return True
@ -125,7 +125,11 @@ class ExternalFunction(AbstractDetector):
results = [] results = []
# After solc 0.6.9, calldata arguments are allowed in public functions # After solc 0.6.9, calldata arguments are allowed in public functions
if self.compilation_unit.solc_version >= "0.7." or self.compilation_unit.solc_version in ["0.6.9","0.6.10","0.6.11"]: if self.compilation_unit.solc_version >= "0.7." or self.compilation_unit.solc_version in [
"0.6.9",
"0.6.10",
"0.6.11",
]:
return results return results
# Create a set to track contracts with dynamic calls. All contracts with dynamic calls could potentially be # Create a set to track contracts with dynamic calls. All contracts with dynamic calls could potentially be
@ -151,13 +155,13 @@ class ExternalFunction(AbstractDetector):
# Next we'll want to loop through all functions defined directly in this contract. # Next we'll want to loop through all functions defined directly in this contract.
for function in contract.functions_declared: for function in contract.functions_declared:
# If all of the function arguments are non-reference type or calldata, we skip it. # If all of the function arguments are non-reference type or calldata, we skip it.
reference_args = [] reference_args = []
for arg in function.parameters: for arg in function.parameters:
if self.is_reference_type(arg) and arg.location == 'memory': if self.is_reference_type(arg) and arg.location == "memory":
reference_args.append(arg) reference_args.append(arg)
if len(reference_args) == 0: if len(reference_args) == 0:
continue continue
# If the function is a constructor, or is public, we skip it. # If the function is a constructor, or is public, we skip it.
if function.is_constructor or function.visibility != "public": if function.is_constructor or function.visibility != "public":

@ -514,7 +514,7 @@ ALL_TEST_OBJECTS = [
all_detectors.ExternalFunction, all_detectors.ExternalFunction,
"external_function_3.sol", "external_function_3.sol",
"0.4.25", "0.4.25",
), ),
Test( Test(
all_detectors.ExternalFunction, all_detectors.ExternalFunction,
"external_function.sol", "external_function.sol",
@ -529,7 +529,7 @@ ALL_TEST_OBJECTS = [
all_detectors.ExternalFunction, all_detectors.ExternalFunction,
"external_function_3.sol", "external_function_3.sol",
"0.5.16", "0.5.16",
), ),
Test( Test(
all_detectors.ExternalFunction, all_detectors.ExternalFunction,
"external_function.sol", "external_function.sol",
@ -544,7 +544,7 @@ ALL_TEST_OBJECTS = [
all_detectors.ExternalFunction, all_detectors.ExternalFunction,
"external_function_3.sol", "external_function_3.sol",
"0.6.11", "0.6.11",
), ),
Test( Test(
all_detectors.ExternalFunction, all_detectors.ExternalFunction,
"external_function.sol", "external_function.sol",
@ -559,7 +559,7 @@ ALL_TEST_OBJECTS = [
all_detectors.ExternalFunction, all_detectors.ExternalFunction,
"external_function_3.sol", "external_function_3.sol",
"0.7.6", "0.7.6",
), ),
Test( Test(
all_detectors.NamingConvention, all_detectors.NamingConvention,
"naming_convention.sol", "naming_convention.sol",

Loading…
Cancel
Save