From 4a241c586818adddc6d93f998c1499e76838fb9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?LUKE=E2=84=A2?= Date: Tue, 1 Aug 2023 12:39:29 +1000 Subject: [PATCH 01/32] Write file on each save --- .gitignore | 5 ++++- slither/core/slither_core.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4441c03d1..a895c22ee 100644 --- a/.gitignore +++ b/.gitignore @@ -114,4 +114,7 @@ test_artifacts/ crytic-export/ # Auto-generated Github pages docs -docs/ \ No newline at end of file +docs/ + +# slither.db.json +slither.db.json diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 798008707..3304d52bd 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -466,6 +466,7 @@ class SlitherCore(Context): def save_results_to_hide(self, results: List[Dict]) -> None: self._results_to_hide += results + self.write_results_to_hide() def add_path_to_filter(self, path: str): """ From e38966c5f75ec8dbc8ba6a56585483275101c329 Mon Sep 17 00:00:00 2001 From: "Khang Vo (doublevkay)" Date: Wed, 25 Oct 2023 16:54:24 +0700 Subject: [PATCH 02/32] detect reinitializer in unprotected_upgrade detector --- .../statements/unprotected_upgradeable.py | 12 ++++- tests/e2e/compilation/test_resolution.py | 6 +-- ...gradeable_0_4_25_AnyInitializer_sol__0.txt | 1 + ...pgradeable_0_4_25_Reinitializer_sol__0.txt | 1 + ...gradeable_0_5_16_AnyInitializer_sol__0.txt | 1 + ...pgradeable_0_5_16_Reinitializer_sol__0.txt | 1 + ...gradeable_0_6_11_AnyInitializer_sol__0.txt | 1 + ...pgradeable_0_6_11_Reinitializer_sol__0.txt | 1 + ...pgradeable_0_7_6_AnyInitializer_sol__0.txt | 1 + ...Upgradeable_0_7_6_Reinitializer_sol__0.txt | 1 + ...gradeable_0_8_15_AnyInitializer_sol__0.txt | 1 + ...pgradeable_0_8_15_Reinitializer_sol__0.txt | 1 + .../0.4.25/AnyInitializer.sol | 15 ++++++ .../0.4.25/AnyInitializer.sol-0.4.25.zip | Bin 0 -> 2867 bytes .../0.4.25/Initializable.sol | 14 +++-- .../0.4.25/Reinitializer.sol | 15 ++++++ .../0.4.25/Reinitializer.sol-0.4.25.zip | Bin 0 -> 2874 bytes .../0.5.16/AnyInitializer.sol | 15 ++++++ .../0.5.16/AnyInitializer.sol-0.5.16.zip | Bin 0 -> 2968 bytes .../0.5.16/Initializable.sol | 14 +++-- .../0.5.16/Reinitializer.sol | 15 ++++++ .../0.5.16/Reinitializer.sol-0.5.16.zip | Bin 0 -> 2977 bytes .../0.6.11/AnyInitializer.sol | 15 ++++++ .../0.6.11/AnyInitializer.sol-0.6.11.zip | Bin 0 -> 3699 bytes .../0.6.11/Initializable.sol | 14 +++-- .../0.6.11/Reinitializer.sol | 15 ++++++ .../0.6.11/Reinitializer.sol-0.6.11.zip | Bin 0 -> 3721 bytes .../0.7.6/AnyInitializer.sol | 15 ++++++ .../0.7.6/AnyInitializer.sol-0.7.6.zip | Bin 0 -> 3594 bytes .../0.7.6/Initializable.sol | 8 ++- .../0.7.6/Reinitializer.sol | 15 ++++++ .../0.7.6/Reinitializer.sol-0.7.6.zip | Bin 0 -> 3622 bytes .../0.8.15/AnyInitializer.sol | 15 ++++++ .../0.8.15/AnyInitializer.sol-0.8.15.zip | Bin 0 -> 3666 bytes .../0.8.15/Initializable.sol | 6 ++- .../0.8.15/Reinitializer.sol | 15 ++++++ .../0.8.15/Reinitializer.sol-0.8.15.zip | Bin 0 -> 3691 bytes tests/e2e/detectors/test_detectors.py | 50 ++++++++++++++++++ 38 files changed, 262 insertions(+), 22 deletions(-) create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt create mode 100644 tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol-0.4.25.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol-0.4.25.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol-0.5.16.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol-0.5.16.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol-0.6.11.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol-0.6.11.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol-0.7.6.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol-0.7.6.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol-0.8.15.zip create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol create mode 100644 tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol-0.8.15.zip diff --git a/slither/detectors/statements/unprotected_upgradeable.py b/slither/detectors/statements/unprotected_upgradeable.py index 30e6300f1..b03211423 100644 --- a/slither/detectors/statements/unprotected_upgradeable.py +++ b/slither/detectors/statements/unprotected_upgradeable.py @@ -50,9 +50,19 @@ def _whitelisted_modifiers(f: Function) -> bool: return "onlyProxy" not in [modifier.name for modifier in f.modifiers] +import re + + def _initialize_functions(contract: Contract) -> List[Function]: return list( - filter(_whitelisted_modifiers, [f for f in contract.functions if f.name == "initialize"]) + filter( + _whitelisted_modifiers, + [ + f + for f in contract.functions + if any((m.name in ["initializer", "reinitializer"]) for m in f.modifiers) + ], + ) ) diff --git a/tests/e2e/compilation/test_resolution.py b/tests/e2e/compilation/test_resolution.py index af7cbe2c7..c3290624b 100644 --- a/tests/e2e/compilation/test_resolution.py +++ b/tests/e2e/compilation/test_resolution.py @@ -57,6 +57,6 @@ def test_contract_function_parameter(solc_binary_path) -> None: function = contract.functions[0] parameters = function.parameters - assert (parameters[0].name == 'param1') - assert (parameters[1].name == '') - assert (parameters[2].name == 'param3') + assert parameters[0].name == "param1" + assert parameters[1].name == "" + assert parameters[2].name == "param3" diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt new file mode 100644 index 000000000..1ca788ced --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_AnyInitializer_sol__0.txt @@ -0,0 +1 @@ +AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt new file mode 100644 index 000000000..79cc306fe --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_4_25_Reinitializer_sol__0.txt @@ -0,0 +1 @@ +Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/Reinitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt new file mode 100644 index 000000000..36309ced3 --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_AnyInitializer_sol__0.txt @@ -0,0 +1 @@ +AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/AnyInitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt new file mode 100644 index 000000000..99eac307d --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_5_16_Reinitializer_sol__0.txt @@ -0,0 +1 @@ +Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt new file mode 100644 index 000000000..dc9612b83 --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_AnyInitializer_sol__0.txt @@ -0,0 +1 @@ +AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt new file mode 100644 index 000000000..270842423 --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_6_11_Reinitializer_sol__0.txt @@ -0,0 +1 @@ +Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt new file mode 100644 index 000000000..5a4ccf71a --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_AnyInitializer_sol__0.txt @@ -0,0 +1 @@ +AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/AnyInitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt new file mode 100644 index 000000000..f79c9c662 --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_7_6_Reinitializer_sol__0.txt @@ -0,0 +1 @@ +Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.7.6/Reinitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt new file mode 100644 index 000000000..fb08aab17 --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_AnyInitializer_sol__0.txt @@ -0,0 +1 @@ +AnyInitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: AnyInitializer.anyName() (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol#6-9). Anyone can delete the contract with: AnyInitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol#11-14) diff --git a/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt new file mode 100644 index 000000000..2eb7d5fee --- /dev/null +++ b/tests/e2e/detectors/snapshots/detectors__detector_UnprotectedUpgradeable_0_8_15_Reinitializer_sol__0.txt @@ -0,0 +1 @@ +Reinitializer (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol#3-15) is an upgradeable contract that does not protect its initialize functions: Reinitializer.initialize() (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol#6-9). Anyone can delete the contract with: Reinitializer.kill() (tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol#11-14) diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol new file mode 100644 index 000000000..9ad63bcdf --- /dev/null +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol @@ -0,0 +1,15 @@ +import "./Initializable.sol"; + +contract AnyInitializer is Initializable { + address owner; + + function anyName() external initializer { + require(owner == address(0)); + owner = msg.sender; + } + + function kill() external { + require(msg.sender == owner); + selfdestruct(owner); + } +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol-0.4.25.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.4.25/AnyInitializer.sol-0.4.25.zip new file mode 100644 index 0000000000000000000000000000000000000000..143c2bc5247ad601d63a91458a6eab99667dacba GIT binary patch literal 2867 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 AU;qFB literal 0 HcmV?d00001 diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol index 779a0e87c..c19577db3 100644 --- a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Initializable.sol @@ -1,5 +1,9 @@ -contract Initializable{ - modifier initializer() { - _; - } -} \ No newline at end of file +contract Initializable { + modifier initializer() { + _; + } + + modifier reinitializer(uint64 version) { + _; + } +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol new file mode 100644 index 000000000..cdf587c49 --- /dev/null +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol @@ -0,0 +1,15 @@ +import "./Initializable.sol"; + +contract Reinitializer is Initializable { + address payable owner; + + function initialize() external reinitializer(2) { + require(owner == address(0)); + owner = msg.sender; + } + + function kill() external { + require(msg.sender == owner); + selfdestruct(owner); + } +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol-0.5.16.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.5.16/Reinitializer.sol-0.5.16.zip new file mode 100644 index 0000000000000000000000000000000000000000..0f8b1e98475645e063a808c52ce50582aaf1252b GIT binary patch literal 2977 zcma);=QkUS0>)#LzV@D>FuA|(UZ001EXfJ#h^v-GvJSMJ0} zy%Kd+k2^x3jVChRm_rqWN42m>{qhG2ftry42Uu~?7C$Xm0`D@Y*)6`c%6}1>WR5D) zh)nfk<5xuS@-4>#udzt<`4auyu@P~afK43~v#IN5*m$m?%q`O>|sUNtm zYQw%kzL*{}6(>S4W3m@;)v1SA#7J4)Td=C_I&CLyo`IYp&Tsw8&#^u-PYN-+Mtz)z=YeseVPbjFfBVXR<}w*wBa(yAlh6qX3$0 zqvXq2c{UJ98ooXF;-<+U)%5M%M%TtCn!O%}ad9fAUSIUVw>DPFTCvAG6zD`gBc&X+A^ zDq4Fr%U3?3UKYcpa0ly9KRWA)A3A1Izp6JDPCiQFURdtsd_oy{jVhJX3bUG4|0K^l z($%Is^-<8vvG1Gpq3n{YI;cz;L0R(Yc4-@2|2j7~9;FDco>!PAncNmiHs8H1=or+= zu=nH5j8c?&sDmvcuA0^=XCj~yaFaVCAmrYC{+uaXYR^O(SV!t{UahOGR4qIn-_=P7 zbD*{tuv~l87bH(B1wR-!Y-@hqD4ym^1{J??)e^4!&@5)K9_gdLviSmrZj?pL-;Tbx z@Sxn$nK#5hckq%5o{v2V$c12$g+LW@+R-cd87vzpeQ~kk82e;1_V;m|l~g)BI8E41 zodw3Vti4(z8F6<$X8am~J{_9I%5v_pS{0ef7MPW9`qe$cLFhO&|^*;Jo2lsX^>=c?_KJJQnJM zq?O#8XsOc3Dllh|)8DPVYFd%J(sdV!D9FdnP%qB~Jmwl#JD^RDyX&+&#sryj-M%+@ z28}rw?2=2uvTFwmLfA_qoR;fbE~B`$gY(~LqcU}y&G|WxGgJhi26d;FNp4_6?DVS7Z0CaxME2%a8%>h!ddS9WEUB!=D$ zS3#Tw8F`SxaM^%rS6yT0otbSr5sIC;b}W2Id2TORfr z1{>jxR5K4Lpst)};+N_1Nv%vJMGQGdt;*~k6sTzvz){~-&d9_4Ew&gkSrN@h^WHaE zfJ`Px*Sk5`0gyQZJ#51`aGIwn7k6>Af_856B%)vB@Pd6ODq0-}#*<``jr_(!9(?>X zN93+SoCfW7mguWI8JWm$WD?6wh-(9Mmi$ zwwWxuq{vriorrdb`gfDu!RCHuE8*rLhxzi9vq2xFvrPth=+LoC&e?lPLhshT zTw96WOvW^^&a3IBo36)MaSP0HC5h=I7$>^qq}OXgg0q@If7dI*zn|`+KOfZti<=M> zNx=b;VKZaC=bj5n6GXM0=Fu{@M8|=R2QU$vGuntbk%bTKdO+y_5WjkVuaZD*owv2{ z;C5iO^iXJfLrFe0&Uca^C@UGWm(s3%+(_@Wor$d? zk*M<=)d`v*NSh>W3{VYk;%n1ai;5@>{aY69V#u5uTC^CZd{JT7a8vH8>M!g6((YbC z_0jQJ_KoE?IgRW2vqH;ce(BlQL6rWv+*z~~n3*tljRR_n?zu4cn0;0)U!%5EEc3B4 z*NN}o{Ho}_D^V{^rq912_I7C_C2XSku20=TT*sIn52k4Q;OX2gbNu*u$KKh3_x%PjoxHA2VLU!b<2easWr|o^WOiZ> zJ^eGKAwhYJpkc!}i(nz^s!zfiopsH+UvS0`vqKfb@_Znna(dH`o>-2Zq%V}dr6};c z{_Vi%WKB^2`y3fKlY1Rw)FhVpRUe{iWHCd?)g~TjEi7ogRsC!N4q%9C?@^%hv_@QL zx5#(gr1;qD4}FbJjbw+c`^_B5BF!iz`JJlXm??%s<_c@2u7gX5C8!K%Ul+Th08%)R zoWvY92#A`kX>~jn=(-a2(I~%>$X&G3bJ6 z;n(@KDm?32TTAralDB)e1V`&+BN!2}8p;1Q=YQn+zX>7w7yp+>8^OrP|2-4^( I;m*J7Kfgz^=l}o! literal 0 HcmV?d00001 diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol new file mode 100644 index 000000000..bccbbc3ea --- /dev/null +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol @@ -0,0 +1,15 @@ +import "./Initializable.sol"; + +contract AnyInitializer is Initializable { + address payable owner; + + function anyName() external initializer { + require(owner == address(0)); + owner = payable(msg.sender); + } + + function kill() external { + require(msg.sender == owner); + selfdestruct(owner); + } +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol-0.6.11.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/AnyInitializer.sol-0.6.11.zip new file mode 100644 index 0000000000000000000000000000000000000000..b2608ec1993449eb8e96275638a14b255a68b36b GIT binary patch literal 3699 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 Df2;O| literal 0 HcmV?d00001 diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol index 779a0e87c..c19577db3 100644 --- a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Initializable.sol @@ -1,5 +1,9 @@ -contract Initializable{ - modifier initializer() { - _; - } -} \ No newline at end of file +contract Initializable { + modifier initializer() { + _; + } + + modifier reinitializer(uint64 version) { + _; + } +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol new file mode 100644 index 000000000..d8a81a4ce --- /dev/null +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol @@ -0,0 +1,15 @@ +import "./Initializable.sol"; + +contract Reinitializer is Initializable { + address payable owner; + + function initialize() external reinitializer(2) { + require(owner == address(0)); + owner = payable(msg.sender); + } + + function kill() external { + require(msg.sender == owner); + selfdestruct(owner); + } +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol-0.6.11.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.6.11/Reinitializer.sol-0.6.11.zip new file mode 100644 index 0000000000000000000000000000000000000000..a74cdfdf4d8b6b88d23c6ea9f1deca66155804f1 GIT binary patch literal 3721 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 literal 0 HcmV?d00001 diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol new file mode 100644 index 000000000..bccbbc3ea --- /dev/null +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol @@ -0,0 +1,15 @@ +import "./Initializable.sol"; + +contract AnyInitializer is Initializable { + address payable owner; + + function anyName() external initializer { + require(owner == address(0)); + owner = payable(msg.sender); + } + + function kill() external { + require(msg.sender == owner); + selfdestruct(owner); + } +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol-0.8.15.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/AnyInitializer.sol-0.8.15.zip new file mode 100644 index 0000000000000000000000000000000000000000..9da08b61b090ac06cfad5660e4b6d09d5ce3ebfa GIT binary patch literal 3666 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 VsNW;`&zs=i>ixUh|H=^n_&--P_3Quu literal 0 HcmV?d00001 diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol index 4fd7561c8..a095b7227 100644 --- a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Initializable.sol @@ -6,10 +6,14 @@ contract Initializable { _; } + modifier reinitializer(uint64 version) { + _; + } + function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; } } -} \ No newline at end of file +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol new file mode 100644 index 000000000..d8a81a4ce --- /dev/null +++ b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol @@ -0,0 +1,15 @@ +import "./Initializable.sol"; + +contract Reinitializer is Initializable { + address payable owner; + + function initialize() external reinitializer(2) { + require(owner == address(0)); + owner = payable(msg.sender); + } + + function kill() external { + require(msg.sender == owner); + selfdestruct(owner); + } +} diff --git a/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol-0.8.15.zip b/tests/e2e/detectors/test_data/unprotected-upgrade/0.8.15/Reinitializer.sol-0.8.15.zip new file mode 100644 index 0000000000000000000000000000000000000000..e58f71c44bf6463efc884abc9f72584f15f2e395 GIT binary patch literal 3691 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 literal 0 HcmV?d00001 diff --git a/tests/e2e/detectors/test_detectors.py b/tests/e2e/detectors/test_detectors.py index 28dcc5e75..a3dc933a3 100644 --- a/tests/e2e/detectors/test_detectors.py +++ b/tests/e2e/detectors/test_detectors.py @@ -938,6 +938,16 @@ ALL_TESTS = [ "whitelisted.sol", "0.4.25", ), + Test( + all_detectors.UnprotectedUpgradeable, + "Reinitializer.sol", + "0.4.25", + ), + Test( + all_detectors.UnprotectedUpgradeable, + "AnyInitializer.sol", + "0.4.25", + ), Test( all_detectors.UnprotectedUpgradeable, "Buggy.sol", @@ -953,6 +963,16 @@ ALL_TESTS = [ "whitelisted.sol", "0.5.16", ), + Test( + all_detectors.UnprotectedUpgradeable, + "Reinitializer.sol", + "0.5.16", + ), + Test( + all_detectors.UnprotectedUpgradeable, + "AnyInitializer.sol", + "0.5.16", + ), Test( all_detectors.UnprotectedUpgradeable, "Buggy.sol", @@ -968,6 +988,16 @@ ALL_TESTS = [ "whitelisted.sol", "0.6.11", ), + Test( + all_detectors.UnprotectedUpgradeable, + "Reinitializer.sol", + "0.6.11", + ), + Test( + all_detectors.UnprotectedUpgradeable, + "AnyInitializer.sol", + "0.6.11", + ), Test( all_detectors.UnprotectedUpgradeable, "Buggy.sol", @@ -978,6 +1008,16 @@ ALL_TESTS = [ "Fixed.sol", "0.7.6", ), + Test( + all_detectors.UnprotectedUpgradeable, + "Reinitializer.sol", + "0.7.6", + ), + Test( + all_detectors.UnprotectedUpgradeable, + "AnyInitializer.sol", + "0.7.6", + ), Test( all_detectors.UnprotectedUpgradeable, "whitelisted.sol", @@ -998,6 +1038,16 @@ ALL_TESTS = [ "whitelisted.sol", "0.8.15", ), + Test( + all_detectors.UnprotectedUpgradeable, + "Reinitializer.sol", + "0.8.15", + ), + Test( + all_detectors.UnprotectedUpgradeable, + "AnyInitializer.sol", + "0.8.15", + ), Test( all_detectors.ABIEncoderV2Array, "storage_ABIEncoderV2_array.sol", From 314ceeb3c28b84a955e1dc010342c328ed5162e7 Mon Sep 17 00:00:00 2001 From: "Khang Vo (doublevkay)" Date: Thu, 26 Oct 2023 16:47:13 +0700 Subject: [PATCH 03/32] remove ambiguous relation between _is_upgradeable and _is_upgradeable_proxy --- slither/core/declarations/contract.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 458f951f5..359658cbd 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -1337,8 +1337,6 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods def is_upgradeable(self) -> bool: if self._is_upgradeable is None: self._is_upgradeable = False - if self.is_upgradeable_proxy: - return False initializable = self.file_scope.get_contract_from_name("Initializable") if initializable: if initializable in self.inheritance: From 2b81c02c612929c26bded0b32f87fde7d05ea040 Mon Sep 17 00:00:00 2001 From: "Khang Vo (doublevkay)" Date: Mon, 30 Oct 2023 12:08:20 +0700 Subject: [PATCH 04/32] make lint --- slither/detectors/statements/unprotected_upgradeable.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/slither/detectors/statements/unprotected_upgradeable.py b/slither/detectors/statements/unprotected_upgradeable.py index b03211423..59f27fc58 100644 --- a/slither/detectors/statements/unprotected_upgradeable.py +++ b/slither/detectors/statements/unprotected_upgradeable.py @@ -49,10 +49,6 @@ def _whitelisted_modifiers(f: Function) -> bool: # https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/3dec82093ea4a490d63aab3e925fed4f692909e8/contracts/proxy/utils/UUPSUpgradeable.sol#L38-L42 return "onlyProxy" not in [modifier.name for modifier in f.modifiers] - -import re - - def _initialize_functions(contract: Contract) -> List[Function]: return list( filter( From ca851e2d079fb601826e3ad09458cb00af9b64e3 Mon Sep 17 00:00:00 2001 From: "Khang Vo (doublevkay)" Date: Mon, 30 Oct 2023 12:08:50 +0700 Subject: [PATCH 05/32] make lint --- slither/detectors/statements/unprotected_upgradeable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/slither/detectors/statements/unprotected_upgradeable.py b/slither/detectors/statements/unprotected_upgradeable.py index 59f27fc58..d25aff187 100644 --- a/slither/detectors/statements/unprotected_upgradeable.py +++ b/slither/detectors/statements/unprotected_upgradeable.py @@ -49,6 +49,7 @@ def _whitelisted_modifiers(f: Function) -> bool: # https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/3dec82093ea4a490d63aab3e925fed4f692909e8/contracts/proxy/utils/UUPSUpgradeable.sol#L38-L42 return "onlyProxy" not in [modifier.name for modifier in f.modifiers] + def _initialize_functions(contract: Contract) -> List[Function]: return list( filter( From eba14c9fae7f1ef801c873c99976b69d94c89080 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Tue, 2 Jan 2024 18:14:29 +0100 Subject: [PATCH 06/32] Add more academic references --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 0f548d6b8..51eed6ff4 100644 --- a/README.md +++ b/README.md @@ -300,5 +300,12 @@ Title | Usage | Authors | Venue | Code [Do Not Rug on Me: Leveraging Machine Learning Techniques for Automated Scam Detection](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract tokens' features (mintable, pausable, ..) | Mazorra, Bruno, Victor Adan, and Vanesa Daza | Mathematics 10.6 (2022) [MANDO: Multi-Level Heterogeneous Graph Embeddings for Fine-Grained Detection of Smart Contract Vulnerabilities](https://arxiv.org/abs/2208.13252) | Use Slither to extract the CFG and call graph | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang| IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | [ge-sc](https://github.com/MANDO-Project/ge-sc) [Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.cs.toronto.edu/~fanl/papers/price-icbc22.pdf) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification) +[Modeling and Enforcing Access Control Policies for Smart Contracts](https://publikationen.bibliothek.kit.edu/1000152805/151859658) | Extend Slither's data dependencies | Jan-Philipp Toberg, Jonas Schiffl, Frederik Reiche, Bernhard Beckert, Robert Heinrich, Ralf Reussner | IEEE International Conference on Decentralized Applications and Infrastructures (DAPPS), 2022 | [SolidityAccessControlEnforcement](https://github.com/KASTEL-CSSDA/SolidityAccessControlEnforcement) +[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 | +[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 | +[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | +[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | +[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | +Storage State Analysis and Extraction of Ethereum Blockchain Smart Contracts (no pdf in open access) | Rely on Slither's CFG and AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | [SmartMuv](https://github.com/WaizKhan7/SmartMuv) If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/). From d54728c62258fae3c861b2ebee9dce7bb9d0c9fa Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Wed, 13 Mar 2024 12:03:54 +0100 Subject: [PATCH 07/32] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 51eed6ff4..85d794e19 100644 --- a/README.md +++ b/README.md @@ -301,11 +301,11 @@ Title | Usage | Authors | Venue | Code [MANDO: Multi-Level Heterogeneous Graph Embeddings for Fine-Grained Detection of Smart Contract Vulnerabilities](https://arxiv.org/abs/2208.13252) | Use Slither to extract the CFG and call graph | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang| IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | [ge-sc](https://github.com/MANDO-Project/ge-sc) [Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.cs.toronto.edu/~fanl/papers/price-icbc22.pdf) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification) [Modeling and Enforcing Access Control Policies for Smart Contracts](https://publikationen.bibliothek.kit.edu/1000152805/151859658) | Extend Slither's data dependencies | Jan-Philipp Toberg, Jonas Schiffl, Frederik Reiche, Bernhard Beckert, Robert Heinrich, Ralf Reussner | IEEE International Conference on Decentralized Applications and Infrastructures (DAPPS), 2022 | [SolidityAccessControlEnforcement](https://github.com/KASTEL-CSSDA/SolidityAccessControlEnforcement) -[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 | -[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 | -[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | -[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | -[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | +[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 | +[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 | +[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | +[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | +[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | Storage State Analysis and Extraction of Ethereum Blockchain Smart Contracts (no pdf in open access) | Rely on Slither's CFG and AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | [SmartMuv](https://github.com/WaizKhan7/SmartMuv) If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/). From f10759c045c4d301783d29bac09c45ce4be6478e Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Wed, 13 Mar 2024 12:08:58 +0100 Subject: [PATCH 08/32] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 85d794e19..d0336e7f2 100644 --- a/README.md +++ b/README.md @@ -306,6 +306,6 @@ Title | Usage | Authors | Venue | Code [Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | [Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | [Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | -Storage State Analysis and Extraction of Ethereum Blockchain Smart Contracts (no pdf in open access) | Rely on Slither's CFG and AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | [SmartMuv](https://github.com/WaizKhan7/SmartMuv) +Storage State Analysis and Extraction of Ethereum Blockchain Smart Contracts (no PDF in open access) | Rely on Slither's CFG and AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | [SmartMuv](https://github.com/WaizKhan7/SmartMuv) If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/). From 3905158cb5ce71eec200e7589dcdb051e6e86c46 Mon Sep 17 00:00:00 2001 From: Feist Josselin Date: Wed, 13 Mar 2024 12:25:16 +0100 Subject: [PATCH 09/32] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d0336e7f2..4d9e1d10e 100644 --- a/README.md +++ b/README.md @@ -301,11 +301,11 @@ Title | Usage | Authors | Venue | Code [MANDO: Multi-Level Heterogeneous Graph Embeddings for Fine-Grained Detection of Smart Contract Vulnerabilities](https://arxiv.org/abs/2208.13252) | Use Slither to extract the CFG and call graph | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang| IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | [ge-sc](https://github.com/MANDO-Project/ge-sc) [Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.cs.toronto.edu/~fanl/papers/price-icbc22.pdf) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification) [Modeling and Enforcing Access Control Policies for Smart Contracts](https://publikationen.bibliothek.kit.edu/1000152805/151859658) | Extend Slither's data dependencies | Jan-Philipp Toberg, Jonas Schiffl, Frederik Reiche, Bernhard Beckert, Robert Heinrich, Ralf Reussner | IEEE International Conference on Decentralized Applications and Infrastructures (DAPPS), 2022 | [SolidityAccessControlEnforcement](https://github.com/KASTEL-CSSDA/SolidityAccessControlEnforcement) -[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 | -[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 | -[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | -[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | -[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | +[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 +[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 +[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 +[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 +[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 Storage State Analysis and Extraction of Ethereum Blockchain Smart Contracts (no PDF in open access) | Rely on Slither's CFG and AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | [SmartMuv](https://github.com/WaizKhan7/SmartMuv) If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/). From 41f599b5463c2518cf71d41556e0597cda298f4b Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 22 Aug 2022 17:50:35 +0200 Subject: [PATCH 10/32] Remove libraries, mock contract, option interfaces --- slither/__main__.py | 8 ++++++++ slither/printers/inheritance/inheritance_graph.py | 8 ++++++-- slither/slither.py | 4 +++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index caaef5730..d303aebe6 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -335,6 +335,14 @@ def parse_args( default=defaults_flag_in_config["printers_to_run"], ) + group_printer.add_argument( + "--exclude-interfaces", + help= "Exclude interfaces from inheritance-graph printer", + action="store_true", + dest="exclude_interfaces", + default=False, + ) + group_detector.add_argument( "--list-detectors", help="List available detectors", diff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py index a16ce273a..3a91f1523 100644 --- a/slither/printers/inheritance/inheritance_graph.py +++ b/slither/printers/inheritance/inheritance_graph.py @@ -98,12 +98,14 @@ class PrinterInheritanceGraph(AbstractPrinter): """ ret = "" + inheritance = [i for i in contract.immediate_inheritance if "mock" not in i.name.lower()] + # Add arrows (number them if there is more than one path so we know order of declaration for inheritance). - if len(contract.immediate_inheritance) == 1: + if len(inheritance) == 1: immediate_inheritance = contract.immediate_inheritance[0] ret += f"c{contract.id}_{contract.name} -> c{immediate_inheritance.id}_{immediate_inheritance};\n" else: - for i, immediate_inheritance in enumerate(contract.immediate_inheritance): + for i, immediate_inheritance in enumerate(inheritance): ret += f'c{contract.id}_{contract.name} -> c{immediate_inheritance.id}_{immediate_inheritance} [ label="{i + 1}" ];\n' # Functions @@ -195,6 +197,8 @@ class PrinterInheritanceGraph(AbstractPrinter): content = 'digraph "" {\n' for c in self.contracts: + if c.is_top_level or "mock" in c.name.lower() or c.is_library or (self.slither.exclude_interfaces and c.is_interface): + continue content += self._summary(c) + "\n" content += "}" diff --git a/slither/slither.py b/slither/slither.py index 0f2218535..72cf36536 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -196,10 +196,12 @@ class Slither( if printers_to_run == "echidna": self.skip_data_dependency = True + # Used in inheritance-graph printer + self.exclude_interfaces = kwargs.get("exclude_interfaces", False) + self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) def _init_parsing_and_analyses(self, skip_analyze: bool) -> None: - for parser in self._parsers: try: parser.parse_contracts() From ea01702294bf8b2e4c512063402020a795e68cf1 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 22 Aug 2022 18:04:23 +0200 Subject: [PATCH 11/32] Fix remove interfaces inherited --- slither/printers/inheritance/inheritance_graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py index 3a91f1523..36fb6c432 100644 --- a/slither/printers/inheritance/inheritance_graph.py +++ b/slither/printers/inheritance/inheritance_graph.py @@ -98,7 +98,7 @@ class PrinterInheritanceGraph(AbstractPrinter): """ ret = "" - inheritance = [i for i in contract.immediate_inheritance if "mock" not in i.name.lower()] + inheritance = [i for i in contract.immediate_inheritance if "mock" not in i.name.lower() and (self.slither.exclude_interfaces and not i.is_interface)] # Add arrows (number them if there is more than one path so we know order of declaration for inheritance). if len(inheritance) == 1: From 4164039011de66c076981d5f652c076a2ab53a96 Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 22 Aug 2022 18:14:14 +0200 Subject: [PATCH 12/32] Fix --- slither/printers/inheritance/inheritance_graph.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py index 36fb6c432..a593d20ee 100644 --- a/slither/printers/inheritance/inheritance_graph.py +++ b/slither/printers/inheritance/inheritance_graph.py @@ -98,7 +98,8 @@ class PrinterInheritanceGraph(AbstractPrinter): """ ret = "" - inheritance = [i for i in contract.immediate_inheritance if "mock" not in i.name.lower() and (self.slither.exclude_interfaces and not i.is_interface)] + # Remove contracts that have "mock" in the name and if --exclude-interface removes inherited interfaces + inheritance = [i for i in contract.immediate_inheritance if "mock" not in i.name.lower() and (not self.slither.exclude_interfaces or self.slither.exclude_interfaces and not i.is_interface)] # Add arrows (number them if there is more than one path so we know order of declaration for inheritance). if len(inheritance) == 1: From 20fa97cbacb33330da75f2678313f2727fc6d0a5 Mon Sep 17 00:00:00 2001 From: Alexis Date: Tue, 9 Apr 2024 17:18:02 +0200 Subject: [PATCH 13/32] Remove interface from inheritance graph. --- slither/__main__.py | 6 +++--- .../printers/inheritance/inheritance_graph.py | 17 ++++++++++++++--- slither/slither.py | 2 +- .../test_data/test_contract_names/C.sol | 16 +++++++++++++++- tests/e2e/printers/test_printers.py | 12 ++++++++++++ 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index d303aebe6..de818c288 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -336,10 +336,10 @@ def parse_args( ) group_printer.add_argument( - "--exclude-interfaces", - help= "Exclude interfaces from inheritance-graph printer", + "--include-interfaces", + help="Include interfaces from inheritance-graph printer", action="store_true", - dest="exclude_interfaces", + dest="include_interfaces", default=False, ) diff --git a/slither/printers/inheritance/inheritance_graph.py b/slither/printers/inheritance/inheritance_graph.py index a593d20ee..54b525c77 100644 --- a/slither/printers/inheritance/inheritance_graph.py +++ b/slither/printers/inheritance/inheritance_graph.py @@ -98,8 +98,14 @@ class PrinterInheritanceGraph(AbstractPrinter): """ ret = "" - # Remove contracts that have "mock" in the name and if --exclude-interface removes inherited interfaces - inheritance = [i for i in contract.immediate_inheritance if "mock" not in i.name.lower() and (not self.slither.exclude_interfaces or self.slither.exclude_interfaces and not i.is_interface)] + # Remove contracts that have "mock" in the name and if --include-interfaces in False (default) + # removes inherited interfaces + inheritance = [ + i + for i in contract.immediate_inheritance + if "mock" not in i.name.lower() + and (not i.is_interface or self.slither.include_interfaces) + ] # Add arrows (number them if there is more than one path so we know order of declaration for inheritance). if len(inheritance) == 1: @@ -116,6 +122,7 @@ class PrinterInheritanceGraph(AbstractPrinter): for f in contract.functions if not f.is_constructor and not f.is_constructor_variables + and not f.is_virtual and f.contract_declarer == contract and f.visibility in visibilities ] @@ -198,7 +205,11 @@ class PrinterInheritanceGraph(AbstractPrinter): content = 'digraph "" {\n' for c in self.contracts: - if c.is_top_level or "mock" in c.name.lower() or c.is_library or (self.slither.exclude_interfaces and c.is_interface): + if ( + "mock" in c.name.lower() + or c.is_library + or (c.is_interface and not self.slither.include_interfaces) + ): continue content += self._summary(c) + "\n" content += "}" diff --git a/slither/slither.py b/slither/slither.py index 72cf36536..7adc0694c 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -197,7 +197,7 @@ class Slither( self.skip_data_dependency = True # Used in inheritance-graph printer - self.exclude_interfaces = kwargs.get("exclude_interfaces", False) + self.include_interfaces = kwargs.get("include_interfaces", False) self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) diff --git a/tests/e2e/printers/test_data/test_contract_names/C.sol b/tests/e2e/printers/test_data/test_contract_names/C.sol index 90bc35df3..d6ba9b5c1 100644 --- a/tests/e2e/printers/test_data/test_contract_names/C.sol +++ b/tests/e2e/printers/test_data/test_contract_names/C.sol @@ -1,7 +1,21 @@ import "./A.sol"; -contract C is A { +interface MyInterfaceX { + function count() external view returns (uint256); + + function increment() external; +} + +contract C is A, MyInterfaceX { function c_main() public pure { a_main(); } + + function count() external view override returns (uint256){ + return 1; + } + + function increment() external override { + + } } diff --git a/tests/e2e/printers/test_printers.py b/tests/e2e/printers/test_printers.py index 26429d338..3dea8b74a 100644 --- a/tests/e2e/printers/test_printers.py +++ b/tests/e2e/printers/test_printers.py @@ -34,3 +34,15 @@ def test_inheritance_printer(solc_binary_path) -> None: assert counter["B -> A"] == 2 assert counter["C -> A"] == 1 + + # Lets also test the include/exclude interface behavior + # Check that the interface is not included + assert "MyInterfaceX" not in content + + slither.include_interfaces = True + output = printer.output("test_printer.dot") + content = output.elements[0]["name"]["content"] + assert "MyInterfaceX" in content + + # Remove test generated files + Path("test_printer.dot").unlink(missing_ok=True) From 6074ab1c3821e7d040512582756be789844b06c4 Mon Sep 17 00:00:00 2001 From: Alexis Date: Fri, 19 Apr 2024 10:54:37 +0200 Subject: [PATCH 14/32] Remove calls to isinstance to improve performances. --- slither/visitors/expression/expression.py | 79 +++++++++-------------- 1 file changed, 29 insertions(+), 50 deletions(-) diff --git a/slither/visitors/expression/expression.py b/slither/visitors/expression/expression.py index 41886a102..860ca2850 100644 --- a/slither/visitors/expression/expression.py +++ b/slither/visitors/expression/expression.py @@ -1,4 +1,5 @@ import logging +from functools import cache from slither.core.expressions.assignment_operation import AssignmentOperation from slither.core.expressions.binary_operation import BinaryOperation @@ -21,6 +22,28 @@ from slither.exceptions import SlitherError logger = logging.getLogger("ExpressionVisitor") +@cache +def get_visitor_mapping(): + """Returns a visitor mapping from expression type to visiting functions.""" + return { + AssignmentOperation: '_visit_assignement_operation', + BinaryOperation: '_visit_binary_operation', + CallExpression: '_visit_call_expression', + ConditionalExpression: '_visit_conditional_expression', + ElementaryTypeNameExpression: '_visit_elementary_type_name_expression', + Identifier: '_visit_identifier', + IndexAccess: '_visit_index_access', + Literal: '_visit_literal', + MemberAccess: '_visit_member_access', + NewArray: '_visit_new_array', + NewContract: '_visit_new_contract', + NewElementaryType: '_visit_new_elementary_type', + TupleExpression: '_visit_tuple_expression', + TypeConversion: '_visit_type_conversion', + UnaryOperation: '_visit_unary_operation' + } + + # pylint: disable=too-few-public-methods class ExpressionVisitor: def __init__(self, expression: Expression) -> None: @@ -35,60 +58,16 @@ class ExpressionVisitor: # visit an expression # call pre_visit, visit_expression_name, post_visit - # pylint: disable=too-many-branches def _visit_expression(self, expression: Expression) -> None: self._pre_visit(expression) - if isinstance(expression, AssignmentOperation): - self._visit_assignement_operation(expression) - - elif isinstance(expression, BinaryOperation): - self._visit_binary_operation(expression) - - elif isinstance(expression, CallExpression): - self._visit_call_expression(expression) - - elif isinstance(expression, ConditionalExpression): - self._visit_conditional_expression(expression) - - elif isinstance(expression, ElementaryTypeNameExpression): - self._visit_elementary_type_name_expression(expression) - - elif isinstance(expression, Identifier): - self._visit_identifier(expression) - - elif isinstance(expression, IndexAccess): - self._visit_index_access(expression) - - elif isinstance(expression, Literal): - self._visit_literal(expression) - - elif isinstance(expression, MemberAccess): - self._visit_member_access(expression) - - elif isinstance(expression, NewArray): - self._visit_new_array(expression) - - elif isinstance(expression, NewContract): - self._visit_new_contract(expression) - - elif isinstance(expression, NewElementaryType): - self._visit_new_elementary_type(expression) - - elif isinstance(expression, TupleExpression): - self._visit_tuple_expression(expression) + if expression is not None: + visitor_method = get_visitor_mapping().get(expression.__class__) + if not visitor_method: + raise SlitherError(f"Expression not handled: {expression}") - elif isinstance(expression, TypeConversion): - self._visit_type_conversion(expression) - - elif isinstance(expression, UnaryOperation): - self._visit_unary_operation(expression) - - elif expression is None: - pass - - else: - raise SlitherError(f"Expression not handled: {expression}") + visitor = getattr(self, visitor_method) + visitor(expression) self._post_visit(expression) From 6afe440924369910cd33890256ad6afb7677ce1a Mon Sep 17 00:00:00 2001 From: Alexis Date: Fri, 19 Apr 2024 10:54:52 +0200 Subject: [PATCH 15/32] Memoize calls to __str__ --- slither/core/slither_core.py | 10 +- slither/core/solidity_types/array_type.py | 4 +- .../core/solidity_types/elementary_type.py | 4 +- slither/core/solidity_types/mapping_type.py | 4 +- .../slither_compilation_unit_solc.py | 127 ++++++++++-------- 5 files changed, 92 insertions(+), 57 deletions(-) diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 8eca260fa..727c2e44c 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -35,6 +35,14 @@ def _relative_path_format(path: str) -> str: return path.split("..")[-1].strip(".").strip("/") +def empty_tuple_list(): + return [(-1, -1)] + + +def tuple_dict(): + return defaultdict(empty_tuple_list) + + # pylint: disable=too-many-instance-attributes,too-many-public-methods class SlitherCore(Context): """ @@ -80,7 +88,7 @@ class SlitherCore(Context): # Maps from file to detector name to the start/end ranges for that detector. # Infinity is used to signal a detector has no end range. self._ignore_ranges: Dict[str, Dict[str, List[Tuple[int, ...]]]] = defaultdict( - lambda: defaultdict(lambda: [(-1, -1)]) + tuple_dict ) self._compilation_units: List[SlitherCompilationUnit] = [] diff --git a/slither/core/solidity_types/array_type.py b/slither/core/solidity_types/array_type.py index 04a458d68..254125891 100644 --- a/slither/core/solidity_types/array_type.py +++ b/slither/core/solidity_types/array_type.py @@ -1,3 +1,4 @@ +from functools import cache from typing import Union, Optional, Tuple, Any, TYPE_CHECKING from slither.core.expressions.expression import Expression @@ -66,6 +67,7 @@ class ArrayType(Type): return elem_size * int(str(self._length_value)), True return 32, True + @cache def __str__(self) -> str: if self._length: return str(self._type) + f"[{str(self._length_value)}]" @@ -77,4 +79,4 @@ class ArrayType(Type): return self._type == other.type and self._length_value == other.length_value def __hash__(self) -> int: - return hash(str(self)) + return hash(self._type) diff --git a/slither/core/solidity_types/elementary_type.py b/slither/core/solidity_types/elementary_type.py index a9f45c8d8..63c3071ed 100644 --- a/slither/core/solidity_types/elementary_type.py +++ b/slither/core/solidity_types/elementary_type.py @@ -1,4 +1,5 @@ import itertools +from functools import cache from typing import Tuple, Optional, Any from slither.core.solidity_types.type import Type @@ -216,6 +217,7 @@ class ElementaryType(Type): return MaxValues[self.name] raise SlitherException(f"{self.name} does not have a max value") + @cache def __str__(self) -> str: return self._type @@ -225,4 +227,4 @@ class ElementaryType(Type): return self.type == other.type def __hash__(self) -> int: - return hash(str(self)) + return hash(self._type) diff --git a/slither/core/solidity_types/mapping_type.py b/slither/core/solidity_types/mapping_type.py index 9741569ed..e7adb461c 100644 --- a/slither/core/solidity_types/mapping_type.py +++ b/slither/core/solidity_types/mapping_type.py @@ -1,3 +1,4 @@ +from functools import cache from typing import Union, Tuple, TYPE_CHECKING, Any from slither.core.solidity_types.type import Type @@ -35,6 +36,7 @@ class MappingType(Type): def is_dynamic(self) -> bool: return True + @cache def __str__(self) -> str: return f"mapping({str(self._from)} => {str(self._to)})" @@ -44,4 +46,4 @@ class MappingType(Type): return self.type_from == other.type_from and self.type_to == other.type_to def __hash__(self) -> int: - return hash(str(self)) + return hash(f"{self._from}.{self._to}") diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 36efeef33..b3bb0d46a 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -1,3 +1,4 @@ +import concurrent.futures from collections import defaultdict import json import logging @@ -73,6 +74,64 @@ def _handle_import_aliases( ) +def generate_slithir_contract(contract): + contract.add_constructor_variables() + + for func in contract.functions + contract.modifiers: + try: + func.generate_slithir_and_analyze() + + except AttributeError as e: + # This can happen for example if there is a call to an interface + # And the interface is redefined due to contract's name reuse + # But the available version misses some functions + # self._underlying_contract_to_parser[contract].log_incorrect_parsing( + # f"Impossible to generate IR for {contract.name}.{func.name} ({func.source_mapping}):\n {e}" + # ) + # TODO(dm) + pass + except Exception as e: + func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) + logger.error( + f"\nFailed to generate IR for {contract.name}.{func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{contract.name}.{func.name} ({func.source_mapping}):\n " + f"{func_expressions}" + ) + raise e + try: + contract.convert_expression_to_slithir_ssa() + except Exception as exc: + logger.error( + f"\nFailed to convert IR to SSA for {contract.name} contract. Please open an issue https://github.com/crytic/slither/issues.\n " + ) + raise exc + + +def generate_slithir_function(func): + try: + func.generate_slithir_and_analyze() + except AttributeError as e: + logger.error( + f"Impossible to generate IR for top level function {func.name} ({func.source_mapping}):\n {e}" + ) + except Exception as e: + func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) + logger.error( + f"\nFailed to generate IR for top level function {func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{func.name} ({func.source_mapping}):\n " + f"{func_expressions}" + ) + raise e + + try: + func.generate_slithir_ssa({}) + except Exception as e: + func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) + logger.error( + f"\nFailed to convert IR to SSA for top level function {func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{func.name} ({func.source_mapping}):\n " + f"{func_expressions}" + ) + raise e + + class SlitherCompilationUnitSolc(CallerContextExpression): # pylint: disable=too-many-instance-attributes def __init__(self, compilation_unit: SlitherCompilationUnit) -> None: @@ -803,60 +862,22 @@ class SlitherCompilationUnitSolc(CallerContextExpression): contract.set_is_analyzed(True) def _convert_to_slithir(self) -> None: - for contract in self._compilation_unit.contracts: - contract.add_constructor_variables() - - for func in contract.functions + contract.modifiers: - try: - func.generate_slithir_and_analyze() - - except AttributeError as e: - # This can happens for example if there is a call to an interface - # And the interface is redefined due to contract's name reuse - # But the available version misses some functions - self._underlying_contract_to_parser[contract].log_incorrect_parsing( - f"Impossible to generate IR for {contract.name}.{func.name} ({func.source_mapping}):\n {e}" - ) - except Exception as e: - func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) - logger.error( - f"\nFailed to generate IR for {contract.name}.{func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{contract.name}.{func.name} ({func.source_mapping}):\n " - f"{func_expressions}" - ) - raise e - try: - contract.convert_expression_to_slithir_ssa() - except Exception as e: - logger.error( - f"\nFailed to convert IR to SSA for {contract.name} contract. Please open an issue https://github.com/crytic/slither/issues.\n " - ) - raise e - - for func in self._compilation_unit.functions_top_level: - try: - func.generate_slithir_and_analyze() - except AttributeError as e: - logger.error( - f"Impossible to generate IR for top level function {func.name} ({func.source_mapping}):\n {e}" - ) - except Exception as e: - func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) - logger.error( - f"\nFailed to generate IR for top level function {func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{func.name} ({func.source_mapping}):\n " - f"{func_expressions}" - ) - raise e - - try: - func.generate_slithir_ssa({}) - except Exception as e: - func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) - logger.error( - f"\nFailed to convert IR to SSA for top level function {func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{func.name} ({func.source_mapping}):\n " - f"{func_expressions}" - ) - raise e + generate_slithir_contract(contract) + + for function in self._compilation_unit.functions_top_level: + generate_slithir_function(function) + # + # with concurrent.futures.ProcessPoolExecutor() as executor: + # + # futures = [ + # executor.submit(generate_slithir_contract, contract) for contract in self._compilation_unit.contracts + # ] + [ + # executor.submit(generate_slithir_function, function) for function in self._compilation_unit.functions_top_level + # ] + # + # for future in concurrent.futures.as_completed(futures): + # future.result() self._compilation_unit.propagate_function_calls() for contract in self._compilation_unit.contracts: From ae6fc40b62c8c4bac7bbc71f4e485e7316bc13d7 Mon Sep 17 00:00:00 2001 From: Alexis Date: Fri, 19 Apr 2024 11:26:43 +0200 Subject: [PATCH 16/32] Remove unneeded metaclass --- slither/core/source_mapping/source_mapping.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/slither/core/source_mapping/source_mapping.py b/slither/core/source_mapping/source_mapping.py index fceab7855..078d5afab 100644 --- a/slither/core/source_mapping/source_mapping.py +++ b/slither/core/source_mapping/source_mapping.py @@ -1,5 +1,4 @@ import re -from abc import ABCMeta from typing import Dict, Union, List, Tuple, TYPE_CHECKING, Optional, Any from Crypto.Hash import SHA1 @@ -183,7 +182,7 @@ def _convert_source_mapping( return new_source -class SourceMapping(Context, metaclass=ABCMeta): +class SourceMapping(Context): def __init__(self) -> None: super().__init__() self.source_mapping: Optional[Source] = None From bb842783674034666df8031a80b5fb716c1b53c8 Mon Sep 17 00:00:00 2001 From: Alexis Date: Fri, 19 Apr 2024 11:52:53 +0200 Subject: [PATCH 17/32] Prevent a call to isinstance in _filter_state_variables_written --- slither/core/declarations/function.py | 9 +++------ slither/core/expressions/identifier.py | 3 +++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index 958a7d219..4829f2102 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -94,14 +94,11 @@ class FunctionType(Enum): def _filter_state_variables_written(expressions: List["Expression"]): ret = [] + for expression in expressions: - if isinstance(expression, Identifier): - ret.append(expression) - if isinstance(expression, UnaryOperation): - ret.append(expression.expression) - if isinstance(expression, MemberAccess): + if isinstance(expression, (Identifier, UnaryOperation, MemberAccess)): ret.append(expression.expression) - if isinstance(expression, IndexAccess): + elif isinstance(expression, IndexAccess): ret.append(expression.expression_left) return ret diff --git a/slither/core/expressions/identifier.py b/slither/core/expressions/identifier.py index 5cd29a9f5..493620ab1 100644 --- a/slither/core/expressions/identifier.py +++ b/slither/core/expressions/identifier.py @@ -78,3 +78,6 @@ class Identifier(Expression): def __str__(self) -> str: return str(self._value) + + def expression(self): + return self From 59caf4bb3fc10b2e04173836eb6ae0f9f3a1d4c4 Mon Sep 17 00:00:00 2001 From: Alexis Date: Fri, 19 Apr 2024 14:08:05 +0200 Subject: [PATCH 18/32] Revert "Memoize calls to __str__" This reverts commit 6afe440924369910cd33890256ad6afb7677ce1a. --- slither/core/slither_core.py | 10 +- slither/core/solidity_types/array_type.py | 4 +- .../core/solidity_types/elementary_type.py | 4 +- slither/core/solidity_types/mapping_type.py | 4 +- .../slither_compilation_unit_solc.py | 127 ++++++++---------- 5 files changed, 57 insertions(+), 92 deletions(-) diff --git a/slither/core/slither_core.py b/slither/core/slither_core.py index 727c2e44c..8eca260fa 100644 --- a/slither/core/slither_core.py +++ b/slither/core/slither_core.py @@ -35,14 +35,6 @@ def _relative_path_format(path: str) -> str: return path.split("..")[-1].strip(".").strip("/") -def empty_tuple_list(): - return [(-1, -1)] - - -def tuple_dict(): - return defaultdict(empty_tuple_list) - - # pylint: disable=too-many-instance-attributes,too-many-public-methods class SlitherCore(Context): """ @@ -88,7 +80,7 @@ class SlitherCore(Context): # Maps from file to detector name to the start/end ranges for that detector. # Infinity is used to signal a detector has no end range. self._ignore_ranges: Dict[str, Dict[str, List[Tuple[int, ...]]]] = defaultdict( - tuple_dict + lambda: defaultdict(lambda: [(-1, -1)]) ) self._compilation_units: List[SlitherCompilationUnit] = [] diff --git a/slither/core/solidity_types/array_type.py b/slither/core/solidity_types/array_type.py index 254125891..04a458d68 100644 --- a/slither/core/solidity_types/array_type.py +++ b/slither/core/solidity_types/array_type.py @@ -1,4 +1,3 @@ -from functools import cache from typing import Union, Optional, Tuple, Any, TYPE_CHECKING from slither.core.expressions.expression import Expression @@ -67,7 +66,6 @@ class ArrayType(Type): return elem_size * int(str(self._length_value)), True return 32, True - @cache def __str__(self) -> str: if self._length: return str(self._type) + f"[{str(self._length_value)}]" @@ -79,4 +77,4 @@ class ArrayType(Type): return self._type == other.type and self._length_value == other.length_value def __hash__(self) -> int: - return hash(self._type) + return hash(str(self)) diff --git a/slither/core/solidity_types/elementary_type.py b/slither/core/solidity_types/elementary_type.py index 63c3071ed..a9f45c8d8 100644 --- a/slither/core/solidity_types/elementary_type.py +++ b/slither/core/solidity_types/elementary_type.py @@ -1,5 +1,4 @@ import itertools -from functools import cache from typing import Tuple, Optional, Any from slither.core.solidity_types.type import Type @@ -217,7 +216,6 @@ class ElementaryType(Type): return MaxValues[self.name] raise SlitherException(f"{self.name} does not have a max value") - @cache def __str__(self) -> str: return self._type @@ -227,4 +225,4 @@ class ElementaryType(Type): return self.type == other.type def __hash__(self) -> int: - return hash(self._type) + return hash(str(self)) diff --git a/slither/core/solidity_types/mapping_type.py b/slither/core/solidity_types/mapping_type.py index e7adb461c..9741569ed 100644 --- a/slither/core/solidity_types/mapping_type.py +++ b/slither/core/solidity_types/mapping_type.py @@ -1,4 +1,3 @@ -from functools import cache from typing import Union, Tuple, TYPE_CHECKING, Any from slither.core.solidity_types.type import Type @@ -36,7 +35,6 @@ class MappingType(Type): def is_dynamic(self) -> bool: return True - @cache def __str__(self) -> str: return f"mapping({str(self._from)} => {str(self._to)})" @@ -46,4 +44,4 @@ class MappingType(Type): return self.type_from == other.type_from and self.type_to == other.type_to def __hash__(self) -> int: - return hash(f"{self._from}.{self._to}") + return hash(str(self)) diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index b3bb0d46a..36efeef33 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -1,4 +1,3 @@ -import concurrent.futures from collections import defaultdict import json import logging @@ -74,64 +73,6 @@ def _handle_import_aliases( ) -def generate_slithir_contract(contract): - contract.add_constructor_variables() - - for func in contract.functions + contract.modifiers: - try: - func.generate_slithir_and_analyze() - - except AttributeError as e: - # This can happen for example if there is a call to an interface - # And the interface is redefined due to contract's name reuse - # But the available version misses some functions - # self._underlying_contract_to_parser[contract].log_incorrect_parsing( - # f"Impossible to generate IR for {contract.name}.{func.name} ({func.source_mapping}):\n {e}" - # ) - # TODO(dm) - pass - except Exception as e: - func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) - logger.error( - f"\nFailed to generate IR for {contract.name}.{func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{contract.name}.{func.name} ({func.source_mapping}):\n " - f"{func_expressions}" - ) - raise e - try: - contract.convert_expression_to_slithir_ssa() - except Exception as exc: - logger.error( - f"\nFailed to convert IR to SSA for {contract.name} contract. Please open an issue https://github.com/crytic/slither/issues.\n " - ) - raise exc - - -def generate_slithir_function(func): - try: - func.generate_slithir_and_analyze() - except AttributeError as e: - logger.error( - f"Impossible to generate IR for top level function {func.name} ({func.source_mapping}):\n {e}" - ) - except Exception as e: - func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) - logger.error( - f"\nFailed to generate IR for top level function {func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{func.name} ({func.source_mapping}):\n " - f"{func_expressions}" - ) - raise e - - try: - func.generate_slithir_ssa({}) - except Exception as e: - func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) - logger.error( - f"\nFailed to convert IR to SSA for top level function {func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{func.name} ({func.source_mapping}):\n " - f"{func_expressions}" - ) - raise e - - class SlitherCompilationUnitSolc(CallerContextExpression): # pylint: disable=too-many-instance-attributes def __init__(self, compilation_unit: SlitherCompilationUnit) -> None: @@ -862,22 +803,60 @@ class SlitherCompilationUnitSolc(CallerContextExpression): contract.set_is_analyzed(True) def _convert_to_slithir(self) -> None: + for contract in self._compilation_unit.contracts: - generate_slithir_contract(contract) - - for function in self._compilation_unit.functions_top_level: - generate_slithir_function(function) - # - # with concurrent.futures.ProcessPoolExecutor() as executor: - # - # futures = [ - # executor.submit(generate_slithir_contract, contract) for contract in self._compilation_unit.contracts - # ] + [ - # executor.submit(generate_slithir_function, function) for function in self._compilation_unit.functions_top_level - # ] - # - # for future in concurrent.futures.as_completed(futures): - # future.result() + contract.add_constructor_variables() + + for func in contract.functions + contract.modifiers: + try: + func.generate_slithir_and_analyze() + + except AttributeError as e: + # This can happens for example if there is a call to an interface + # And the interface is redefined due to contract's name reuse + # But the available version misses some functions + self._underlying_contract_to_parser[contract].log_incorrect_parsing( + f"Impossible to generate IR for {contract.name}.{func.name} ({func.source_mapping}):\n {e}" + ) + except Exception as e: + func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) + logger.error( + f"\nFailed to generate IR for {contract.name}.{func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{contract.name}.{func.name} ({func.source_mapping}):\n " + f"{func_expressions}" + ) + raise e + try: + contract.convert_expression_to_slithir_ssa() + except Exception as e: + logger.error( + f"\nFailed to convert IR to SSA for {contract.name} contract. Please open an issue https://github.com/crytic/slither/issues.\n " + ) + raise e + + for func in self._compilation_unit.functions_top_level: + try: + func.generate_slithir_and_analyze() + except AttributeError as e: + logger.error( + f"Impossible to generate IR for top level function {func.name} ({func.source_mapping}):\n {e}" + ) + except Exception as e: + func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) + logger.error( + f"\nFailed to generate IR for top level function {func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{func.name} ({func.source_mapping}):\n " + f"{func_expressions}" + ) + raise e + + try: + func.generate_slithir_ssa({}) + except Exception as e: + func_expressions = "\n".join([f"\t{ex}" for ex in func.expressions]) + logger.error( + f"\nFailed to convert IR to SSA for top level function {func.name}. Please open an issue https://github.com/crytic/slither/issues.\n{func.name} ({func.source_mapping}):\n " + f"{func_expressions}" + ) + raise e self._compilation_unit.propagate_function_calls() for contract in self._compilation_unit.contracts: From 85b39ea915a64e7e5949f857c798a8e22858d2cc Mon Sep 17 00:00:00 2001 From: Alexis Date: Fri, 19 Apr 2024 14:28:33 +0200 Subject: [PATCH 19/32] Add missing expression types --- slither/visitors/expression/expression.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/slither/visitors/expression/expression.py b/slither/visitors/expression/expression.py index 860ca2850..f60fb2b5a 100644 --- a/slither/visitors/expression/expression.py +++ b/slither/visitors/expression/expression.py @@ -17,6 +17,9 @@ from slither.core.expressions.new_elementary_type import NewElementaryType from slither.core.expressions.tuple_expression import TupleExpression from slither.core.expressions.type_conversion import TypeConversion from slither.core.expressions.unary_operation import UnaryOperation +from slither.core.expressions.super_call_expression import SuperCallExpression +from slither.core.expressions.super_identifier import SuperIdentifier +from slither.core.expressions.self_identifier import SelfIdentifier from slither.exceptions import SlitherError logger = logging.getLogger("ExpressionVisitor") @@ -40,7 +43,10 @@ def get_visitor_mapping(): NewElementaryType: '_visit_new_elementary_type', TupleExpression: '_visit_tuple_expression', TypeConversion: '_visit_type_conversion', - UnaryOperation: '_visit_unary_operation' + UnaryOperation: '_visit_unary_operation', + SelfIdentifier: '_visit_identifier', + SuperIdentifier: '_visit_identifier', + SuperCallExpression: '_visit_call_expression', } From 74d88371b4758580f2d550e744fb17f95341ea9f Mon Sep 17 00:00:00 2001 From: Alexis Date: Fri, 19 Apr 2024 16:48:47 +0200 Subject: [PATCH 20/32] Fix bugs in the EVM printer --- slither/analyses/evm/convert.py | 8 ++- slither/printers/summary/evm.py | 86 +++++++++++++++++---------------- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/slither/analyses/evm/convert.py b/slither/analyses/evm/convert.py index 5e8c4a128..fe294798e 100644 --- a/slither/analyses/evm/convert.py +++ b/slither/analyses/evm/convert.py @@ -178,15 +178,14 @@ def generate_source_to_evm_ins_mapping(evm_instructions, srcmap_runtime, slither # In order to compress these source mappings especially for bytecode, the following rules are used: # If a field is empty, the value of the preceding element is used. # If a : is missing, all following fields are considered empty. - mapping_item = mapping.split(":") mapping_item += prev_mapping[len(mapping_item) :] for i, _ in enumerate(mapping_item): if mapping_item[i] == "": - mapping_item[i] = int(prev_mapping[i]) + mapping_item[i] = prev_mapping[i] - offset, _length, file_id, *_ = mapping_item + offset, _, file_id, *_ = mapping_item prev_mapping = mapping_item if file_id == "-1": @@ -194,8 +193,7 @@ def generate_source_to_evm_ins_mapping(evm_instructions, srcmap_runtime, slither # See https://github.com/ethereum/solidity/issues/6119#issuecomment-467797635 continue - offset = int(offset) - line_number = file_source[0:offset].count("\n".encode("utf-8")) + 1 + line_number = file_source[0 : int(offset)].count("\n".encode("utf-8")) + 1 # Append evm instructions to the corresponding source line number # Note: Some evm instructions in mapping are not necessarily in program execution order diff --git a/slither/printers/summary/evm.py b/slither/printers/summary/evm.py index aad71bdff..b834eb6eb 100644 --- a/slither/printers/summary/evm.py +++ b/slither/printers/summary/evm.py @@ -2,8 +2,11 @@ Module printing evm mapping of the contract """ import logging +from typing import Union, List, Dict from slither.printers.abstract_printer import AbstractPrinter +from slither.core.declarations.function import Function +from slither.core.declarations.modifier import Modifier from slither.analyses.evm import ( generate_source_to_evm_ins_mapping, load_evm_cfg_builder, @@ -77,6 +80,33 @@ class PrinterEVM(AbstractPrinter): WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#evm" + def build_element_node_str( + self, + element: Union["Modifier", "Function"], + contract_pcs: Dict[int, List[int]], + contract_cfg, + ) -> str: + element_file = self.slither.source_code[ + element.contract_declarer.source_mapping.filename.absolute + ].splitlines() + + return_string = "" + for node in element.nodes: + return_string += green(f"\t\tNode: {node}\n") + node_source_line = node.source_mapping.lines[0] + return_string += green( + f"\t\tSource line {node_source_line}: {element_file[node_source_line - 1].rstrip()}\n" + ) + + return_string += magenta("\t\tEVM Instructions:\n") + node_pcs = contract_pcs.get(node_source_line, []) + for pc in node_pcs: + return_string += magenta( + f"\t\t\t{hex(pc)}: {contract_cfg.get_instruction_at(pc)}\n" + ) + + return return_string + def output(self, _filename): """ _filename is not used @@ -99,53 +129,27 @@ class PrinterEVM(AbstractPrinter): txt += "\tempty contract\n" continue - contract_file = self.slither.source_code[ - contract.source_mapping.filename.absolute - ].encode("utf-8") - with open(contract.source_mapping.filename.absolute, "r", encoding="utf8") as f: - contract_file_lines = f.readlines() - - contract_pcs = {} - contract_cfg = {} - for function in contract.functions: txt += blue(f"\tFunction {function.canonical_name}\n") - # CFG and source mapping depend on function being constructor or not - if function.is_constructor: - contract_cfg = evm_info["cfg_init", contract.name] - contract_pcs = evm_info["mapping_init", contract.name] - else: - contract_cfg = evm_info["cfg", contract.name] - contract_pcs = evm_info["mapping", contract.name] - - for node in function.nodes: - txt += green("\t\tNode: " + str(node) + "\n") - node_source_line = ( - contract_file[0 : node.source_mapping.start].count("\n".encode("utf-8")) + 1 - ) - txt += green( - f"\t\tSource line {node_source_line}: {contract_file_lines[node_source_line - 1].rstrip()}\n" - ) - txt += magenta("\t\tEVM Instructions:\n") - node_pcs = contract_pcs.get(node_source_line, []) - for pc in node_pcs: - txt += magenta(f"\t\t\t{hex(pc)}: {contract_cfg.get_instruction_at(pc)}\n") + txt += self.build_element_node_str( + function, + evm_info["mapping", contract.name] + if not function.is_constructor + else evm_info["mapping_init", contract.name], + evm_info["cfg", contract.name] + if not function.is_constructor + else evm_info["cfg_init", contract.name], + ) for modifier in contract.modifiers: txt += blue(f"\tModifier {modifier.canonical_name}\n") - for node in modifier.nodes: - txt += green("\t\tNode: " + str(node) + "\n") - node_source_line = ( - contract_file[0 : node.source_mapping.start].count("\n".encode("utf-8")) + 1 - ) - txt += green( - f"\t\tSource line {node_source_line}: {contract_file_lines[node_source_line - 1].rstrip()}\n" - ) - txt += magenta("\t\tEVM Instructions:\n") - node_pcs = contract_pcs.get(node_source_line, []) - for pc in node_pcs: - txt += magenta(f"\t\t\t{hex(pc)}: {contract_cfg.get_instruction_at(pc)}\n") + + txt += self.build_element_node_str( + modifier, + evm_info["mapping", contract.name], + evm_info["cfg", contract.name], + ) self.info(txt) res = self.generate_output(txt) From 68adb6e05465dfc2ecf546d57e92abfddde81294 Mon Sep 17 00:00:00 2001 From: Alexis Date: Mon, 22 Apr 2024 11:09:47 +0200 Subject: [PATCH 21/32] Continue performance improvments --- slither/core/declarations/custom_error.py | 1 + slither/core/declarations/import_directive.py | 2 + slither/core/declarations/pragma_directive.py | 1 + .../core/solidity_types/elementary_type.py | 2 +- slither/core/solidity_types/type_alias.py | 1 + slither/core/source_mapping/source_mapping.py | 42 +++++++++++++------ slither/utils/source_mapping.py | 28 ++----------- slither/visitors/expression/expression.py | 36 ++++++++-------- 8 files changed, 58 insertions(+), 55 deletions(-) diff --git a/slither/core/declarations/custom_error.py b/slither/core/declarations/custom_error.py index 234873eac..6e2cf142f 100644 --- a/slither/core/declarations/custom_error.py +++ b/slither/core/declarations/custom_error.py @@ -17,6 +17,7 @@ class CustomError(SourceMapping): self._solidity_signature: Optional[str] = None self._full_name: Optional[str] = None + self._pattern = "error" @property def name(self) -> str: diff --git a/slither/core/declarations/import_directive.py b/slither/core/declarations/import_directive.py index 19ea2cff9..440b09e9c 100644 --- a/slither/core/declarations/import_directive.py +++ b/slither/core/declarations/import_directive.py @@ -16,6 +16,8 @@ class Import(SourceMapping): # Map local name -> original name self.renaming: Dict[str, str] = {} + self._pattern = "import" + @property def filename(self) -> str: """ diff --git a/slither/core/declarations/pragma_directive.py b/slither/core/declarations/pragma_directive.py index cd790d5a4..90c1da2dd 100644 --- a/slither/core/declarations/pragma_directive.py +++ b/slither/core/declarations/pragma_directive.py @@ -11,6 +11,7 @@ class Pragma(SourceMapping): super().__init__() self._directive = directive self.scope: "FileScope" = scope + self._pattern = "pragma" @property def directive(self) -> List[str]: diff --git a/slither/core/solidity_types/elementary_type.py b/slither/core/solidity_types/elementary_type.py index a9f45c8d8..61729b06a 100644 --- a/slither/core/solidity_types/elementary_type.py +++ b/slither/core/solidity_types/elementary_type.py @@ -225,4 +225,4 @@ class ElementaryType(Type): return self.type == other.type def __hash__(self) -> int: - return hash(str(self)) + return hash(self._type) diff --git a/slither/core/solidity_types/type_alias.py b/slither/core/solidity_types/type_alias.py index ead9b5394..c22cd257e 100644 --- a/slither/core/solidity_types/type_alias.py +++ b/slither/core/solidity_types/type_alias.py @@ -15,6 +15,7 @@ class TypeAlias(Type): super().__init__() self.name = name self.underlying_type = underlying_type + self._pattern = "type" @property def type(self) -> ElementaryType: diff --git a/slither/core/source_mapping/source_mapping.py b/slither/core/source_mapping/source_mapping.py index 078d5afab..8dda25a24 100644 --- a/slither/core/source_mapping/source_mapping.py +++ b/slither/core/source_mapping/source_mapping.py @@ -98,21 +98,29 @@ class Source: return f"{filename_short}{lines}" def __hash__(self) -> int: - return hash(str(self)) + return hash( + ( + self.start, + self.length, + self.filename.relative, + self.end, + ) + ) def __eq__(self, other: Any) -> bool: - if not isinstance(other, type(self)): + try: + return ( + self.start == other.start + and self.length == other.length + and self.filename == other.filename + and self.is_dependency == other.is_dependency + and self.lines == other.lines + and self.starting_column == other.starting_column + and self.ending_column == other.ending_column + and self.end == other.end + ) + except AttributeError: return NotImplemented - return ( - self.start == other.start - and self.length == other.length - and self.filename == other.filename - and self.is_dependency == other.is_dependency - and self.lines == other.lines - and self.starting_column == other.starting_column - and self.ending_column == other.ending_column - and self.end == other.end - ) def _compute_line( @@ -188,6 +196,8 @@ class SourceMapping(Context): self.source_mapping: Optional[Source] = None self.references: List[Source] = [] + self._pattern: Union[str, None] = None + def set_offset( self, offset: Union["Source", str], compilation_unit: "SlitherCompilationUnit" ) -> None: @@ -203,3 +213,11 @@ class SourceMapping(Context): ) -> None: s = _convert_source_mapping(offset, compilation_unit) self.references.append(s) + + @property + def pattern(self) -> str: + if self._pattern is None: + # Add " " to look after the first solidity keyword + return f" {self.name}" # pylint: disable=no-member + + return self._pattern diff --git a/slither/utils/source_mapping.py b/slither/utils/source_mapping.py index 9bf772894..180c842f7 100644 --- a/slither/utils/source_mapping.py +++ b/slither/utils/source_mapping.py @@ -2,37 +2,17 @@ from typing import List, Set from crytic_compile import CryticCompile from slither.core.declarations import ( Contract, - Function, - Enum, - Event, - Import, - Pragma, - Structure, - CustomError, FunctionContract, ) -from slither.core.solidity_types import Type, TypeAlias from slither.core.source_mapping.source_mapping import Source, SourceMapping -from slither.core.variables.variable import Variable from slither.exceptions import SlitherError def get_definition(target: SourceMapping, crytic_compile: CryticCompile) -> Source: - if isinstance(target, (Contract, Function, Enum, Event, Structure, Variable)): - # Add " " to look after the first solidity keyword - pattern = " " + target.name - elif isinstance(target, Import): - pattern = "import" - elif isinstance(target, Pragma): - pattern = "pragma" # todo maybe return with the while pragma statement - elif isinstance(target, CustomError): - pattern = "error" - elif isinstance(target, TypeAlias): - pattern = "type" - elif isinstance(target, Type): - raise SlitherError("get_definition_generic not implemented for types") - else: - raise SlitherError(f"get_definition_generic not implemented for {type(target)}") + try: + pattern = target.pattern + except AttributeError as exc: + raise SlitherError(f"get_definition_generic not implemented for {type(target)}") from exc file_content = crytic_compile.src_content_for_file(target.source_mapping.filename.absolute) txt = file_content[ diff --git a/slither/visitors/expression/expression.py b/slither/visitors/expression/expression.py index f60fb2b5a..f72727386 100644 --- a/slither/visitors/expression/expression.py +++ b/slither/visitors/expression/expression.py @@ -29,24 +29,24 @@ logger = logging.getLogger("ExpressionVisitor") def get_visitor_mapping(): """Returns a visitor mapping from expression type to visiting functions.""" return { - AssignmentOperation: '_visit_assignement_operation', - BinaryOperation: '_visit_binary_operation', - CallExpression: '_visit_call_expression', - ConditionalExpression: '_visit_conditional_expression', - ElementaryTypeNameExpression: '_visit_elementary_type_name_expression', - Identifier: '_visit_identifier', - IndexAccess: '_visit_index_access', - Literal: '_visit_literal', - MemberAccess: '_visit_member_access', - NewArray: '_visit_new_array', - NewContract: '_visit_new_contract', - NewElementaryType: '_visit_new_elementary_type', - TupleExpression: '_visit_tuple_expression', - TypeConversion: '_visit_type_conversion', - UnaryOperation: '_visit_unary_operation', - SelfIdentifier: '_visit_identifier', - SuperIdentifier: '_visit_identifier', - SuperCallExpression: '_visit_call_expression', + AssignmentOperation: "_visit_assignement_operation", + BinaryOperation: "_visit_binary_operation", + CallExpression: "_visit_call_expression", + ConditionalExpression: "_visit_conditional_expression", + ElementaryTypeNameExpression: "_visit_elementary_type_name_expression", + Identifier: "_visit_identifier", + IndexAccess: "_visit_index_access", + Literal: "_visit_literal", + MemberAccess: "_visit_member_access", + NewArray: "_visit_new_array", + NewContract: "_visit_new_contract", + NewElementaryType: "_visit_new_elementary_type", + TupleExpression: "_visit_tuple_expression", + TypeConversion: "_visit_type_conversion", + UnaryOperation: "_visit_unary_operation", + SelfIdentifier: "_visit_identifier", + SuperIdentifier: "_visit_identifier", + SuperCallExpression: "_visit_call_expression", } From 82f295f2d072f214ebf3f25f9a91fc019fbb2229 Mon Sep 17 00:00:00 2001 From: Alexis Date: Mon, 22 Apr 2024 11:33:03 +0200 Subject: [PATCH 22/32] Replace cache with lru_cache to keep Py3.8 compatibility --- slither/visitors/expression/expression.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slither/visitors/expression/expression.py b/slither/visitors/expression/expression.py index f72727386..83dd1be51 100644 --- a/slither/visitors/expression/expression.py +++ b/slither/visitors/expression/expression.py @@ -1,5 +1,5 @@ import logging -from functools import cache +from functools import lru_cache from slither.core.expressions.assignment_operation import AssignmentOperation from slither.core.expressions.binary_operation import BinaryOperation @@ -25,7 +25,7 @@ from slither.exceptions import SlitherError logger = logging.getLogger("ExpressionVisitor") -@cache +@lru_cache() def get_visitor_mapping(): """Returns a visitor mapping from expression type to visiting functions.""" return { From e2daa8ac6e6d583d4b0c9f31bb17b0ad490d52cc Mon Sep 17 00:00:00 2001 From: Ngalim Siregar Date: Tue, 23 Apr 2024 07:24:59 +0700 Subject: [PATCH 23/32] Add detectors_to_include to override exclude args --- slither/__main__.py | 73 +++++++++++++++++++++-------------- slither/utils/command_line.py | 1 + 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/slither/__main__.py b/slither/__main__.py index 4fc83a11e..a4ff784db 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -11,7 +11,7 @@ import pstats import sys import traceback from importlib import metadata -from typing import Tuple, Optional, List, Dict, Type, Union, Any, Sequence +from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union from crytic_compile import cryticparser, CryticCompile, InvalidCompilation @@ -211,47 +211,54 @@ def choose_detectors( if args.detectors_to_run == "all": detectors_to_run = all_detector_classes - if args.detectors_to_exclude: - detectors_excluded = args.detectors_to_exclude.split(",") - for detector in detectors: - if detector in detectors_excluded: - detectors_to_run.remove(detectors[detector]) else: - for detector in args.detectors_to_run.split(","): - if detector in detectors: - detectors_to_run.append(detectors[detector]) - else: - raise ValueError(f"Error: {detector} is not a detector") - detectors_to_run = sorted(detectors_to_run, key=lambda x: x.IMPACT) + detectors_to_run = __include_detectors( + set(detectors_to_run), args.detectors_to_run, detectors + ) return detectors_to_run - if args.exclude_optimization: - detectors_to_run = [ - d for d in detectors_to_run if d.IMPACT != DetectorClassification.OPTIMIZATION - ] + classification_map = { + DetectorClassification.HIGH: args.exclude_high, + DetectorClassification.MEDIUM: args.exclude_medium, + DetectorClassification.LOW: args.exclude_low, + DetectorClassification.INFORMATIONAL: args.exclude_informational, + DetectorClassification.OPTIMIZATION: args.exclude_optimization, + } + excluded_classification = [ + classification for classification, included in classification_map.items() if included + ] + detectors_to_run = [d for d in detectors_to_run if d.IMPACT not in excluded_classification] - if args.exclude_informational: - detectors_to_run = [ - d for d in detectors_to_run if d.IMPACT != DetectorClassification.INFORMATIONAL - ] - if args.exclude_low: - detectors_to_run = [d for d in detectors_to_run if d.IMPACT != DetectorClassification.LOW] - if args.exclude_medium: - detectors_to_run = [ - d for d in detectors_to_run if d.IMPACT != DetectorClassification.MEDIUM - ] - if args.exclude_high: - detectors_to_run = [d for d in detectors_to_run if d.IMPACT != DetectorClassification.HIGH] if args.detectors_to_exclude: detectors_to_run = [ d for d in detectors_to_run if d.ARGUMENT not in args.detectors_to_exclude ] - detectors_to_run = sorted(detectors_to_run, key=lambda x: x.IMPACT) + if args.detectors_to_include: + detectors_to_run = __include_detectors( + set(detectors_to_run), args.detectors_to_include, detectors + ) return detectors_to_run +def __include_detectors( + detectors_to_run: Set[Type[AbstractDetector]], + detectors_to_include: str, + detectors: Dict[str, Type[AbstractDetector]], +) -> List[Type[AbstractDetector]]: + include_detectors = detectors_to_include.split(",") + + for detector in include_detectors: + if detector in detectors: + detectors_to_run.add(detectors[detector]) + else: + raise ValueError(f"Error: {detector} is not a detector") + + detectors_to_run = sorted(detectors_to_run, key=lambda x: x.IMPACT) + return detectors_to_run + + def choose_printers( args: argparse.Namespace, all_printer_classes: List[Type[AbstractPrinter]] ) -> List[Type[AbstractPrinter]]: @@ -407,6 +414,14 @@ def parse_args( default=defaults_flag_in_config["exclude_high"], ) + group_detector.add_argument( + "--include-detectors", + help="Comma-separated list of detectors that should be included", + action="store", + dest="detectors_to_include", + default=defaults_flag_in_config["detectors_to_include"], + ) + fail_on_group = group_detector.add_mutually_exclusive_group() fail_on_group.add_argument( "--fail-pedantic", diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index a37e85913..f5b9ab452 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -48,6 +48,7 @@ defaults_flag_in_config = { "detectors_to_run": "all", "printers_to_run": None, "detectors_to_exclude": None, + "detectors_to_include": None, "exclude_dependencies": False, "exclude_informational": False, "exclude_optimization": False, From 0dca6a6760f07f65c37dc19bac6c3e48989e528d Mon Sep 17 00:00:00 2001 From: snoppy Date: Sat, 4 May 2024 17:05:10 +0800 Subject: [PATCH 24/32] chore: fix typos and link update Signed-off-by: snoppy --- slither/tools/documentation/README.md | 2 +- slither/visitors/expression/read_var.py | 4 ++-- slither/visitors/slithir/expression_to_slithir.py | 2 +- slither/vyper_parsing/declarations/contract.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/slither/tools/documentation/README.md b/slither/tools/documentation/README.md index b4b3e6a76..218f2e91d 100644 --- a/slither/tools/documentation/README.md +++ b/slither/tools/documentation/README.md @@ -1,5 +1,5 @@ # slither-documentation -`slither-documentation` uses [codex](https://beta.openai.com) to generate natspec documenation. +`slither-documentation` uses [codex](https://platform.openai.com) to generate natspec documenation. This tool is experimental. See [solmate documentation](https://github.com/montyly/solmate/pull/1) for an example of usage. diff --git a/slither/visitors/expression/read_var.py b/slither/visitors/expression/read_var.py index a0efdde61..9619cfff9 100644 --- a/slither/visitors/expression/read_var.py +++ b/slither/visitors/expression/read_var.py @@ -50,8 +50,8 @@ class ReadVar(ExpressionVisitor): self._result = list(set(get(self.expression))) return self._result - # overide assignement - # dont explore if its direct assignement (we explore if its +=, -=, ...) + # override assignment + # dont explore if its direct assignment (we explore if its +=, -=, ...) def _visit_assignement_operation(self, expression: AssignmentOperation) -> None: if expression.type != AssignmentOperationType.ASSIGN: self._visit_expression(expression.expression_left) diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 0f91f9bd1..7d0ac4abf 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -188,7 +188,7 @@ class ExpressionToSlithIR(ExpressionVisitor): right = get(expression.expression_right) operation: Operation if isinstance(left, list): # tuple expression: - if isinstance(right, list): # unbox assigment + if isinstance(right, list): # unbox assignment assert len(left) == len(right) for idx, _ in enumerate(left): if ( diff --git a/slither/vyper_parsing/declarations/contract.py b/slither/vyper_parsing/declarations/contract.py index 2acd43e0f..64fab1c54 100644 --- a/slither/vyper_parsing/declarations/contract.py +++ b/slither/vyper_parsing/declarations/contract.py @@ -84,7 +84,7 @@ class ContractVyper: # pylint: disable=too-many-instance-attributes self._structuresNotParsed.append(node) elif isinstance(node, ImportFrom): # TOOD aliases - # We create an `InterfaceDef` sense the compilatuion unit does not contain the actual interface + # We create an `InterfaceDef` sense the compilation unit does not contain the actual interface # https://github.com/vyperlang/vyper/tree/master/vyper/builtins/interfaces if node.module == "vyper.interfaces": interfaces = { From 08d631f6c91a9d4fa64fd0a1ab9a5a110b7614b2 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Wed, 15 May 2024 08:40:40 -0500 Subject: [PATCH 25/32] fix: support array of structs in abi.decode --- slither/visitors/slithir/expression_to_slithir.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/slither/visitors/slithir/expression_to_slithir.py b/slither/visitors/slithir/expression_to_slithir.py index 7d0ac4abf..1d68336bd 100644 --- a/slither/visitors/slithir/expression_to_slithir.py +++ b/slither/visitors/slithir/expression_to_slithir.py @@ -448,12 +448,12 @@ class ExpressionToSlithIR(ExpressionVisitor): right = get(expression.expression_right) operation: Operation # Left can be a type for abi.decode(var, uint[2]) - if isinstance(left, (Type, Contract, Enum)): + if isinstance(left, (Type, Contract, Enum, Structure)): # Nested type are not yet supported by abi.decode, so the assumption # Is that the right variable must be a constant assert isinstance(right, Constant) # Case for abi.decode(var, I[2]) where I is an interface/contract or an enum - if isinstance(left, (Contract, Enum)): + if isinstance(left, (Contract, Enum, Structure)): left = UserDefinedType(left) t = ArrayType(left, int(right.value)) set_val(expression, t) From 22b9cfc39cf96d9188eeca1c72bf122630056d80 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 17 May 2024 15:33:39 -0500 Subject: [PATCH 26/32] fix: use contract declarer's scope for name resolution --- .../solc_parsing/expressions/find_variable.py | 2 +- .../scope_with_renaming/core/MainContract.sol | 41 +++++++++++++++++++ .../core/ParentContract.sol | 30 ++++++++++++++ .../scope_with_renaming/errors/MainErrors.sol | 9 ++++ .../errors/ParentContractErrors.sol | 7 ++++ tests/unit/core/test_scope_with_renaming.py | 17 ++++++++ tests/unit/core/test_using_for.py | 2 +- 7 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 tests/unit/core/test_data/scope_with_renaming/core/MainContract.sol create mode 100644 tests/unit/core/test_data/scope_with_renaming/core/ParentContract.sol create mode 100644 tests/unit/core/test_data/scope_with_renaming/errors/MainErrors.sol create mode 100644 tests/unit/core/test_data/scope_with_renaming/errors/ParentContractErrors.sol create mode 100644 tests/unit/core/test_scope_with_renaming.py diff --git a/slither/solc_parsing/expressions/find_variable.py b/slither/solc_parsing/expressions/find_variable.py index 2d8fa58f6..4ea1239e5 100644 --- a/slither/solc_parsing/expressions/find_variable.py +++ b/slither/solc_parsing/expressions/find_variable.py @@ -304,7 +304,7 @@ def _find_variable_init( scope = underlying_function.file_scope else: assert isinstance(underlying_function, FunctionContract) - scope = underlying_function.contract.file_scope + scope = underlying_function.contract_declarer.file_scope elif isinstance(caller_context, StructureTopLevelSolc): direct_contracts = [] diff --git a/tests/unit/core/test_data/scope_with_renaming/core/MainContract.sol b/tests/unit/core/test_data/scope_with_renaming/core/MainContract.sol new file mode 100644 index 000000000..5eb92aa2f --- /dev/null +++ b/tests/unit/core/test_data/scope_with_renaming/core/MainContract.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import { + ParentContract +} from "./ParentContract.sol"; + +import { + MainErrors as Errors +} from "./../errors/MainErrors.sol"; + + +contract MainContract is ParentContract { + + + function functionWithMainError1(uint256 a, uint256 b) external pure returns (uint256) { + if (a == b) { + revert Errors.MainError1(); + } + // Add some arithmetic operations here + return a + b; + } + + function functionWithMainError2(uint256 a, uint256 b) external pure returns (uint256) { + if (a < b) { + revert Errors.MainError2(); + } + // Add some arithmetic operations here + return a - b; + } + + function functionWithMainError3(uint256 a, uint256 b) external pure returns (uint256) { + if (b == 0) { + revert Errors.MainError3(); + } + // Add some arithmetic operations here + return a * b; + } + + +} diff --git a/tests/unit/core/test_data/scope_with_renaming/core/ParentContract.sol b/tests/unit/core/test_data/scope_with_renaming/core/ParentContract.sol new file mode 100644 index 000000000..9ca32a1a6 --- /dev/null +++ b/tests/unit/core/test_data/scope_with_renaming/core/ParentContract.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + + +import { + AccessControlErrors as Errors +} from "../errors/ParentContractErrors.sol"; + + +contract ParentContract { + + + function functionWithAccessControlErrors1(uint256 a, uint256 b) external pure returns (uint256) { + if (a == b) { + revert Errors.AccessControlErrors1(); + } + // Add some arithmetic operations here + return a + b; + } + + function functionWithAccessControlErrors2(uint256 a, uint256 b) external pure returns (uint256) { + if (a < b) { + revert Errors.AccessControlErrors2(); + } + // Add some arithmetic operations here + return a - b; + } + + +} diff --git a/tests/unit/core/test_data/scope_with_renaming/errors/MainErrors.sol b/tests/unit/core/test_data/scope_with_renaming/errors/MainErrors.sol new file mode 100644 index 000000000..e7db5c5c3 --- /dev/null +++ b/tests/unit/core/test_data/scope_with_renaming/errors/MainErrors.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +// TODO: remove unused errors +library MainErrors { + error MainError1(); + error MainError2(); + error MainError3(); +} diff --git a/tests/unit/core/test_data/scope_with_renaming/errors/ParentContractErrors.sol b/tests/unit/core/test_data/scope_with_renaming/errors/ParentContractErrors.sol new file mode 100644 index 000000000..38ce16bdd --- /dev/null +++ b/tests/unit/core/test_data/scope_with_renaming/errors/ParentContractErrors.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +library AccessControlErrors { + error AccessControlErrors1(); + error AccessControlErrors2(); +} diff --git a/tests/unit/core/test_scope_with_renaming.py b/tests/unit/core/test_scope_with_renaming.py new file mode 100644 index 000000000..6984cfaa4 --- /dev/null +++ b/tests/unit/core/test_scope_with_renaming.py @@ -0,0 +1,17 @@ +from pathlib import Path +from crytic_compile import CryticCompile +from crytic_compile.platform.solc_standard_json import SolcStandardJson + +from slither import Slither + +TEST_DATA_DIR = Path(__file__).resolve().parent / "test_data" +SCOPE_RENAMING_TEST_DATA_DIR = Path(TEST_DATA_DIR, "scope_with_renaming") + +# https://github.com/crytic/slither/issues/2454 +def test_find_variable_scope_with_renaming(solc_binary_path) -> None: + solc_path = solc_binary_path("0.8.24") + standard_json = SolcStandardJson() + for source_file in SCOPE_RENAMING_TEST_DATA_DIR.rglob("**/*.sol"): + standard_json.add_source_file(Path(source_file).as_posix()) + compilation = CryticCompile(standard_json, solc=solc_path) + Slither(compilation, disallow_partial=True) diff --git a/tests/unit/core/test_using_for.py b/tests/unit/core/test_using_for.py index 4d7634c5c..656fc3a35 100644 --- a/tests/unit/core/test_using_for.py +++ b/tests/unit/core/test_using_for.py @@ -17,7 +17,7 @@ def test_using_for_global_collision(solc_binary_path) -> None: for source_file in Path(USING_FOR_TEST_DATA_DIR, "using_for_global_collision").rglob("*.sol"): standard_json.add_source_file(Path(source_file).as_posix()) compilation = CryticCompile(standard_json, solc=solc_path) - sl = Slither(compilation) + sl = Slither(compilation, disallow_partial=True) _run_all_detectors(sl) From 4f661e48077337bca95a8f460aebc96bf19cfb12 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Fri, 17 May 2024 15:48:57 -0500 Subject: [PATCH 27/32] add test for 08d631f --- ...-decode-fixed-array.sol-0.8.10-compact.zip | Bin 4857 -> 5926 bytes ...-decode-fixed-array.sol-0.8.11-compact.zip | Bin 4875 -> 5850 bytes ...-decode-fixed-array.sol-0.8.12-compact.zip | Bin 4870 -> 5887 bytes ...-decode-fixed-array.sol-0.8.13-compact.zip | Bin 4870 -> 5884 bytes ...-decode-fixed-array.sol-0.8.14-compact.zip | Bin 4862 -> 5921 bytes ...-decode-fixed-array.sol-0.8.15-compact.zip | Bin 4868 -> 5892 bytes ...i-decode-fixed-array.sol-0.8.8-compact.zip | Bin 4856 -> 5903 bytes ...decode-fixed-array.sol-0.8.10-compact.json | 3 ++- ...decode-fixed-array.sol-0.8.11-compact.json | 3 ++- ...decode-fixed-array.sol-0.8.12-compact.json | 3 ++- ...decode-fixed-array.sol-0.8.13-compact.json | 3 ++- ...decode-fixed-array.sol-0.8.14-compact.json | 3 ++- ...decode-fixed-array.sol-0.8.15-compact.json | 3 ++- ...-decode-fixed-array.sol-0.8.8-compact.json | 3 ++- .../abi-decode-fixed-array.sol | 7 ++++++- 15 files changed, 20 insertions(+), 8 deletions(-) diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.10-compact.zip index b65e511efb24373d3157a32071cdb114e9b73141..6c43440c91eb829cbb2b655a4ae3daf26a3a65ae 100644 GIT binary patch delta 5809 zcmV;i7EbB;C8jPIP)h>@KL7#%4gj`&u~>ZL^#y1a007d7kr-Zo@kbAZrIlV+*LwgE zaqkuAn-IgL7+&+B!3~Xy@GV}LeF(XZfT-*|EGg331ZN>wm zis85S0YC(iIphE$>ko~Wy^4-kI()G!KnXKbA&ds>IA*IX1;6u68* zWmjLVsv%wuCi?%-UMW;NRr>HFWeG+lUPw^8t&hoIjz|oD*){*z$llqn2E5Bw<_6#< zO`3QEmU?>|{BgeOYR*m3#@)q8d1?JYgBDqq1|#rwPn%9&btCc7W0WAH zwzB2$Ll$L*-?EP3&$L0*7-j!))>=PH3}msA5K%7_EVfIs9guj8AvHo(Ze5*S0Ms*( zIqHHwI8i!(S_!x!*Vok-CjyvlU*J7Np8?HW0OYlUwuOkr0k&gfJMcV`!X!#rmmE=r zjh)N$zsSokNuZlnw4gwK(%?M=1G8L5SR5Fmt~vMs*{t;iT(Ey3Xv1J~PyUa)9J<_tS){+iDULk6{dZ~9W;$AjS8Amy z-jG0lkpU^>?n!<|8bNUW2vZFK#pqwHx)PX;jRsQ~*%*G~A3?9$0kESFfu!e^Rmb^u zFJD=}W<=`k$zOcL>1X-JzWjZ(NNQ||E>KYXA`Rq`8?{9>q$T{cdCyZ3x6tqlghuvC z9P}EdWM7)k7(+l8nJ~9c=l({pt1D7DsB{v4{YqT2?874_Zi`bx2M5l8pPq&|14=6~ z#cx}!cm6%J-5K#cN9{a?5ppD4#4hxQUymhSg3nPF9TPX8H!9{aabO@p0vYMRe6w#O zy_oaT!X*D7wB7Vd=2L%qeqT-?9+$D+5(|0eHh0VwdHKe|Aqlp|8`83p_S`jKsbBPe ze#;XiJ1xFCHyz7p%Ky1Gnx2Wy0Tc9N7ZBR|5LRh2^B1&_0v*q}x=PSZbn)+se2$3d zMl>Ag+~k0Ao=Hb9`gJhV{kjhl01RY>O2jz5_jr48o1n;}mZKJuFaSD&Q&b^^u|)-v zGIS!)TN_07USc;=<+1!8wQA=2#Lb|85NeB51_m>k!LsChSbEB@%xtnxi6tF{mpZ%a z+dszNVvWi)%i(Yt+`<}yR-vf#utdi}cWn1ey=Dk)4|}Dxd|TQqY@;5QIKZ}cBX=@PY*9&7v1Hc9bFC^69-`*@yxdlxALE|XPjlyt4*aPw z?XVHyiF1iut0f_eyO*9Uzq5{i@@@XmvH}R>Irdm<2{l)L=mZh?@~2=ksShPJ+_j${ zmhc1=CeJH2mF;n0GcmXs#b2peHATnBoWdAZ`WJ+-I+b%K4rJMeWh)N7GjZ&$N|N*b zJM&2@iDmy<#%~uE1b*I^w~#v2?qTNPzseO8(>untRqBZ^lQF!H=y zBVbT2=nSMFTb8)TD2?FucT5OUVOmp&_H*U5_Ivk$36}w9KN({KE1fa{Bt+8>)3K?& zPC-)0y3W~eoR_k&1nkoPptCgHPY+@7dE99TjA$*fi?TmOW7PY{qPORBp=mg0M2Cvm zK~VRQhwF)Q`gSCpT)Vq}qo$3ni0UxkPYcwJ z^}Uv;z=W}U(~ez~ce*c@fVK8bquwn$kX1Z<4Ki(oDU*J)-3Czu?mPiL>~Wcg4^Wm{ zkM391^Q~g^24X8kvo~@$gD^4TW7P2=!ejGZ;{izfM~ip8xvHEdVL#d@&S=Xt^?HPS zPn(8+)M|F>Od~dbFfoJ9t>S#&N41A{cG4R0?;HArf!tTNf4U*vIiSr8#r~~#gTldj@tFdI(= zdGVccM?ZKSfaDLmW0q-aCEz(PQi};ElDi`c1xz@joa?45muP464k7y&uk$uBobsv< z$gMt;=<(ct&)4Vo%3nQG5Atsbu`a=qoChQ_GTdu5dC=$|x*T7B(tfa9@u@B1t>)OY zb8d7zFa1nZHCug%7|!ai!9uOtW82y#Cv5z61^o;R(4NSgc0(D4o&7pQbhM=Zur&=|@%3Pl7GLQvGutD4Ar7l#xV;B#l zb$x_?eF|q^y?)RDrs2!U#LzU)1I1&GJ2`<6;h6TtwI-K#FJBhE=4*CJs_o4Y_gRBD zvsKwh7244g1!rH4D*^bQbuHy4(z`SGk9fiS=pS%|Mq+F z!itb=Nb^Hy%V}Tg?E7`F@3RK29QP}I&HQ6z4ME#TX^)xlaqUl<(SgFSH2nI2WQAKH zD8hYeWA*N6og&nS?7!3TWmo>KcPq~R>hxy{reFyRz@JCrI`t?&CFviUklYqJ<$D}| z@ZzsP87RNNU&$sIQ}3AHWNDaJVpycOx)ivl0Nn#$3uoBB=l~-frJFeCxC(n@x%7gOE^?|vm){&4$i9EmA#GY-93YchQbGKz z`A+sURrS0hKP@itvZNMwtii-NJ{{nH)bJ>9V~AI^!i<4?&IP>O?DqrO?Viu4a48B2wY8 zwe92Ynrsv`sCBsRs#Uk8PdGK7Z9a$0Ln>T_i_m;@<7ENfoF<(P5D7u6QFp9=tlUls zztQg3Y+Ec%*6$Pg7PXQ>U3Tme(JQ%AN-9q@N9}rCRjyNqv<_9WJaDhdrW zl0PClD8jN3i2aUbs0#LNMT`|S^K!5+f9?&FJSOFjk4|Ua&GeF9dQ5kMN0M0zw7K3aJl^^ID}!!!yY~7~*@a)hM;j|| z9a{H_`Tj-f%E3wT5>wee9W+*Kyz<1*9jKTkal1pf`0_)harDD8GOgH8XrJ}tDcGZ` z&LMmUa6i*3e)E@Uq7G+TXJ5RUhcN+>v2B`Z6Y-K9=akd)FLPJGSzo<>R|V6xzPgCo zjTMSbii6KfL1ZLgAB1km^8G0F)bV_Grb81eZ#IPMHe z+Jg#zETpRINhvcLsCS}&-lLSna|Ptj5t^MEaSI-|VcOcaZ~*fZzK@)#y5U8{VlM?A zbyV3Y9D)HX_K$X4=1-a!0TsFBCj-oTB)?qti8B6xX5ntsZhD#I5DRoaLHxvovS8qN z%0lR*&aIt#?|s!>){S4O8_It|5E?HZC9`tu+T+~~_FtvdP6F_M=~x-vZ$#uB68kS} zccC;()&sR^ci8?vTs07|X`eB$+Jqi7de`GM|3tr3aT&la$_Ud_1APRdu;u?uIZ_h( zVOx54qqYmM#!7l9*2X{YcGDt;;Uz)l>T}*54cW-RJM_igBU4@#H*$?@2s)=d0~t|t zlVW%Ge3Sh4H;2f7i&Y7e7g2_tJ)FRUAaTRtE{q85uoN5PJ>C|qCAVT`6_~8V^_95r zeHo33nqqwoM}_(h36a@QvrTFio2Kgb=@&x#kh9pQ%qn*-2C*s-bwXbmj(ueMYWEQ> zu)XJ6-KB*`UH_jH8O)90Fa5dyiYylAF{+u;wZ@Oia$rDz2Th{hDjz(MBp65rVD@xz zJh)e?{f9Ntpgp?WXIc_>b|G}3Nk;5$Iy6Ahy<;|zMF}-&Ym0aJzo|f*lr94v#uu>G z%oAR4TyUEng7S@KaikHy+Fx$VVQ>+pi4f2nb^lW#7COm3n}-VP7Dlog^K!hLOaW^g@86NL zlB~p=V%)oH9g%Iyr#?4Z0%HM5#yp0y_<{^B-SXdmDg%FaAigP_@!W{dGB(39Kt;Sd zDvCu!5q2+rT9P1@MEj(Ie#}D410$9Ba3+I-Xb!^L$yY+PhlVfiSlHJLov%H0LvlT^ zfIh=FOZUxjE#qfmp{w}yCich?81S7dhg5O9M{&xma3G3m?g-1wNcn06HVJ_A5MG`BQvENf zRmgnI^ymd6Cgwq+W-@Q7`#{prU1g*9>6&PMAxytfK9ILr9r+4Q_WIL8^m){juINIu z!B5H--}_((aXY!GC|ZcAm)P?`fAHzp0YL|U9S;niwDRf1XSnYLuDPVlgqCgeb|IkU zQLA69_HtcD=HT@dH^J9$MN+&k54&EK2UTa_`_)jnwj)$}01zdbR243iY z3LEnVOf};L5}ry!rqTlbAVB8a_`W_1-#^eybYM0pRCwQM z)C;_l_2n21q5X#UAo@7w=|l@nFpZ@m4Mn66`)n8(Fjlv#x0gm~-PRic^#SN)Ck$p9 z=^xFET!xv)k9@#;ubT(&(!bvraXJHkwJ!YFWecv~Ci2QlH+dFyG(q)AI}J$s@Jt7E z>1%L~_jQw1@IFF$xG1BZ0_2w_#zi?EWP52NOiRI!PX-Z8jEnFeec!6aC)kXvnLeC2 z4ANs;@nn!d6K*cNkV<*E$jgI}xpKA1C4`mU^$2XC`r>oLA&U-q*RVA~YBD*0y+dyf zL=A~$OiqDBs!Fv%y=`~GFl;O|?-5h8wVGi{hk~-Kay0jcsoQ)Y+BUt6 z_QVOLICxxg+>qicns=d?h-;C5{uupTf0;i{K0?L5f1LhyNTUaD4lgAma3k5W=l`+? zX~d|WX0l7}_^GU@&IjdXfd*xw_{VD!bh^2N@2fwEq$wHfe@CAm1eeU<0!j1n>V+wk z>9wN^i3$t@-a@muJ{X7IelsJFT8^&!+N=RgNm$nRYitB|o7sDKF)z}8V4o-eERal} zxL~~~Hh%ccZ3L6XTIQ{K|A90stAai)WoM3py?*yHm2xUACBCx4O}>`=O~(PN2uRFr z33z!4v3SE>Z#s3ub&G-TnsI@6Wm}8eZ7>An8wLxuOE)h_quQypj%LrtLuI0-H(Zfr zBZQ8+=-D+`vTeU71R6YlckT*<4x)GEmAXPt73!m~#ya5|%N^hb1wg11OdXNJqKNuF zXg2WM!0F8@FFI1@D}Q}I{$Jhx^|+d-B4vev=m{*sST1|L)NfNW1UOMNhE^um#A4an z4~NAV4M>IRT(|zoNfXG{E2}yqX4sd$`Ep|XRGyiX$Q6xEpYv;fFjFVPg399Dr11esTIn7=65>CfA2~$WBN2~H=!o#pNzIo>o_d4VuuL3`?+?@drOa^ z?P+LZ&LIZWv5b0i-Cc6UvgV)A*0nIa!XwLMKB$<3mywxv@#LN7R~HbQ*vm0dt7-U2 zH)j$*;>mv@%^)0qZ49=uQArR}AB;c{q5jkeQeE_~@L>WzC)rB?l{@9W?jHW()Kknq zaz;$e^pI#HugVh*W=nE!TLlA5CaiZik?J6x7#KDJRcxEs#VSvFlDP)IU`oQpLegyB zFW<zgvu2zu;UL*TR5Uh5yLf^r2Ke`DDH4n6yeilkV_rNJzy&KxpQ1 z`iU?9p|v=uOkn4$EG|iYBxGGNe`qa(7~zU`Wwikn3~_>JeU` z#K$>nFSn*@Z61x+T2-QAJnx-Tv6->xUirif=@bo7OSfq#p)CoD6`5+W zU0-u25WjT$7xxv+fMOR}yhso=I^|)HE>ZL^#y1J761U!iIbrcQU@KL7#%4ged8mR1nA+rB#z004_-001tN-xe{EOe%l%Lq3k% z8(|US<+$<-R-TXbNE-97FH-K9mq@1&+0=A#oo)!e&BSqqY@)H2tpV5?K7wRBZt4}$ zBS0<)o?y_b*^SqSjR`I~F_hESyTznTO^sF7ofGDHM1q2!s|Un7AY zE3F6f^QfiEOClWkqIsDoWn0eyiyAHOQ@LWN9|nr&-ycwWG+{tnFYE0q>LD-kN%5B> zhP}AENM*k4R%v0>!p(%_DUHHiR9pCSTJHSE-qptxgQj7ij}8NedOS*kg4li%^_{9xR#7cX#GvB-ciFv8lzr zF#!IdikJE#c|lG*-X|Xe&nB6CyVCbUcz-o~3e11!psH7h3V?eQ4uvDm+s9uHc`GGW zWPs;ENGSI5>ZQEc!;3tGj#Y8Qe8AF<+)Otxnt1`ya%WtMXTdTlA=E?O?*E z&^o$!nlEfYrh|b3%c=wDb69bY82{%+UUT)PuBWyITL;j?qfVh3O8bvO@I2+k$dXjP z9PR$0(nB1eZ=|;TeOZ0; zR6P2mis!1z{eKDa_l55#liX$s(9vnD{O_D6t5NiR zsDm(U)QZcjwDl!Lhs7ksnsdj_mUmg(g^{WOv);t6r$R|&k)1Vkc$rS&JapyL%0=K; z*7xxHsG;H|t$%-cjH^467x3nkwsAmF0D z(2j#4_Dg8HR!&s219|jAcTNtkd0dR}_KJ1|2595fakiop=(;7xa1B9(p=^h*Tg6&E2z>~25kh`y znZ2{?uTW`Pz#a^X*~E&r38OyR53v=K5vVGB=y!kn5_(-*q(r=K>*CqEins1{2oFre z77?4+f*%}$lF_l_4D$?_7xNKok;QdOeq?fY7g3bzMY)h*0eEvAHsjdK8<3`Gol>*Y z4s-CVTg}n{f5DCPD*wE#`T8cSUr1w72>)i&wdu3Eec^zp*b=YLkPzE}OgEKBcN09N z+OB`n_?+22%}JdIAmkC|xl4=k<4!UAyGfU@)(K?^2TT*Lu zeRl$!*_>dNSretW*gN(EJ5B=hhDC{qLos5~92r;x*r<~_pZz;Wg`tqnAizyzyft6L zlOX1CpiYGz^|CAx`0%g+_;4S!qkK>sFyc0MfIg;k;_SGk-QcwuB2Y4Ggov%neSPCObtoORGEz&46HduI4u+$K zyX#I0SYhv#GcK0NgfK*!RCC#eJqyhHmGdlX+bJhgdj|5@C;>cCj_$6umYIxq7cXJInMZ_L3aEyB7S8PtzmiV^`FW^@%&N9+DWDvu4G-=`}VhZZu z%R4XZDq86#V(*i)anr-H3oS9DI4{SrHKcc>gwlW=0M2S4QIWO==<|MZ#mBZAUnVZg zI{m+)w=k=nTvto!#On3W{R)2-NXDEdOnx+ek1}X)XiY5|fO9PQJdTx$D($v44db6P z?!y~KC0@E0i=7x=M)4Mp4&>g%O5>hTc~@;Gg_@UdGm&2g*CaK|ozyp}f8s>6&<@1w59GUy{b1krQdXWa9)?JTNCRpxuw z98WK7`S5IKW2vJ)&;7E0u4icMZ^FUAF}Us+zZhjiu>~v+N%7{yWb4i1Hb1vJJE9xo zjqqPtd%JRR?G8xBRI7i3_yA=ykn*VjRHrXtEvy0KNdFCJG$a+6$g{Vrcvko9fU*@e z4|T5RdS`PITSp(t=ZfFUuH5#lvVhzB{BfhSm)^xb>6nJfY*J!96aKj5Fz_3!yo5Sy z@&Oq^8XCc~!7ib&E7grdBbi^t$}utjW@+v|K|gy``Cs8nTr7W;lRibO7B6rPqSOh` zx6nGI{rGi-3wE@zAc*!2w!T|5a+DLS}} zIkKFvW^sP=3*=#5(aT!_hbw`*jwg>t zYF^BTO}zggxm~2BC9mKC)RP&lifmPtH&}FMMIB<(10geOXwR5lP;LSC4Q>#Hue`36 z5lPW{F0q0Kknx~S<$+wI5XeLRrpGmN@Bz}`5Cc-dC6^HM6QeI5i)$sg(zx9s_7^ZG z#?K5^saStjG;0%I`nfG&6FViMyqQv`U}8lbt2;|DY$0tRh}UdySMp(&6i@hgMME~H z*Ep;J*9#*+v}6V!&4cOr{dG456_~9W;_{!iUVb;&V}Z2g?bjw?AftK@=>12Lp;ZiV zyyIpU_ALvdRfigV{b455JoQE3x;wc4`a#;&2nBz9!*Um#iHnViWIm`Tmz_TvfqvP9 zf~oj%`GKo~%KTDbQMqSd{uyb>k{P4NbEbl)NXSI10F9?muv>7+4u99Dl^~BHrm_tN zI=9$P2RsJ`6n*(O*9~p1>(={T%4x0wSvo63(;hvO=!jAJQS5O|OB?)$tS1EwNoyAZ zQjC9^VErlKpDOe-!;m(GW$gwnUzfHm`pz{20G~KZxi_Kfkw%-@jHd*J`*pFA+ij6# z{Z2&g>eW%-@F>h|1SJhKYl3}2FQ6(1RQ(FS&|}PB+0DLNLdFm$DY((_D4Ty9 zZP|lcsE3fxaE)6EEkEtvA7q+|@wh9|s=AuvS9`i_s3GT2>=RSaE%hZ)RqmQM9>4`p z>@~Fn{;DiLN&95Kx3ppv;1&qkTP3o?{AwL;isOKGW#h;7I1eOleX>ex3tkQSy#S02{Wu@!yYuY+` z47ljXCBz&YodHN{LxBLjQ(6*?3Dq-#-(k|Dca^J=2&6KYHm%@DE~@gz%@zmG?$(TYnBE@bZ7L@wcB^ zsv0eo1GAgX8+_DitX}Tzix*P5Yi`XvAU%ycW_s(6?vkaf=^WW9Isrqa@k)eKblh8d zW_q+U?0$EDPA$%b3t$%*$18mOjJ?R4AzuJ=SK*fh-mCMU6IcEM%l%|D6OT81@YRt= z#|zJ!9b4{V>QlKo`lJ5Z}?#v9qp-ihZAB@ zi*VwVSQ^0bi-CL~VK*nWOXJY`n}7q5>Oz$xTp6d*bE18D7#KnV5)6VSPz1V6JC!PJSBg6+F1@h1&t)! zzOQ`L(QL&?KsLrTo$lSQEB!V8LS*!a z7ugElTH86*IbX@gD71fx-&Ry&fd<4z_zQ~pFM{XhTth}VP@_A3t}7t-NNLv9PTN$u z_0(+WfOYC=majpQAAdc?iMj^CfV3E8NjDCL2rmX*IY0Tbn_Em@CzwT^R$#lb_`xgf z8Z=LA&GqMyix8xVsoH#yGs8K8W-Pm>^jAYTzHV}bK~9l0b)J7{-#&6MPFZc=o`=pn zLQ(lL5Vh_DEY7{bHHZCPW*0&*`XS%@%R~}=F9K+&lrnu1);?xgRCRf}|FzCm4mHtL z@Wt9viP%hg=T%eWBPV*CoQH%zVA?wn0*W6V1s>V;;Ayo^7#Ri1XG-cl8G~&~eaFj` zD=s_?ORMfs5CVTF;-q{O1^=8ROLQpc?( zR?m`#(p?uo`G~P%>a?6Quy{90H=HOZKqjDk%u%gRmT$c z)#1i9n$v&QM*M@LgS@qC!)A}+voD%<iT+j5zeBA4iXwQZ_<^8e zEPh3?faJ{_Vb+u;q0Kp^g`O@EsTr<~Y5y4o%Hw~LKarkGJm`CnB-8W^<87*t>z(Mp zbY_?7$4+t0kwdm7p;__JtL}VHBEx-5fL0j{ZZR$SMT?=(HZo>SxW5I_;BFQ|pl@Il zg%D;v2BOUE6bbB#RrH8Now!;3g6CfR+#}Z7o|v0s{^{m5p8bf?K6uxP6X=G~tp*-z zj-`LsTk+*YHZTb-iK9JWpGN3el^}4G)D5IT#zYd}QWqC|1`oG2?O*-P|Tu&Nb(nWUip~*;z zto5&!@I0Npnh=>Px# diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.zip index c9a78fceafc83990aa8d7df96d3f808a8e85035e..6c8b090357e180a9faa878a2620dbf7967c1cc80 100644 GIT binary patch delta 5732 zcmV-q7MtmdCfY3+P)h>@KL7#%4gj`&u~??*M|d0-007d7kr-Zo@kbAZrIlV+*LwgE zaqkuAn-IgLLRAF3Pj$b_d69BkdyAmw}Di;Nl+BoH%x*M>Hje7N74^>M?_m5|`0D&C%koxEWE> zn{xVDXIj}F-M1cAu&)qR$mG)!?r`_$>%?$14N%J2^Q$9&h6IGmzijkIEbbC-i`U@$ zk?Lil`t=2bkjUxAjusr!XZ^}nRT1h~TdOi|2q%WI63nXCTXO$pgOuk8#><&nUyQH; zhMK^Ny)6s{@O;Ks16rA7PCgA|)CP9KNR{Y;4}Z;fwO&z{@S0=9;F}r{kkzYKY4?HJ z^d@LW1gk=SOW$hi-Rj`z7&CjzACPI?j2sDnNPTR7Sf2nZ2xmj`5{C_KSMN{ZNwtqN_qUgb@R|&;1G~RMeLfb3680;Kfb_X6f zSJxjz%uD-}d1GD%oHMYkN|rgOfJ5@w9!g@%;@Q4`>fr#9&Qitk2q2pSLib>DX8~n0 zS2Q);8)Z%KY@t`Z>8~PsEq7h&+e9v+xcO9`Mb3xCb$A&5J4`S{s_ohJ$ZFmh4%WQ) zAw~~ZyP8HNj+fH+NsW1g|#CF-PjtvXl^<1r5^DjcjzK=P2 z_!x39%{Z<7E@a|u%R5(fUNRllpZh17o;}`wj4n?`0-iUVX7J|bmA&k0A~pzVj|QVW z$`@QrJR=_aVylQ~1dBrF?aZ1eh_|(&k5YNr0nhA0X;XFjanD=?Dqu=S@kPnKTWwvm z>oFUXP~7?CeQb(l*wch?nHtfz(EGV`XXISwtC&*Wy{@Fh$i2mk{VZHNEmO;tQQlsE z^m;a<|C(Zm8M+WVmMB{pR?d06s()u}dEx*vfzbVIphv&J@%Q%Jr2xf@ZYRAv%p-%M z$Q3WI!T7t2BPl6HhP^vHJHFIZ=9L-UTc%J-;ddwjGngF2r+Ts)V;arlzg4T!f-^-( zi4$C2S_D!-t!H0SjGR~xui+4pzyG6ugDfn#O@pJJ7%>$Cv($sLdMzJXr1hyNZn(Mb zmD~~z-xQ%0h#et;3elmZJt54JzCP>2(>a_|aouR|DGd(zbKW@r3G|z`r%4}&Hees9 zY~L7v^f_SwO(Mpi5Z0Y^W*NNgKv2cO+t1fdfRl;7O0R1Q@H~HVS@L+$3o%508`9sv zSC(9I{HH&{ZnVtO>Aw_ri?ZknXa}DY1na#YK^h=rN3soGsmb>SlHy7CDrezRAly5N zC7_Ka69KC?_K~o7cSU!o_KRi7i`RgretFk450jDe7$iib?F*jtA8oT-WQc5PqQHgW zXX5A#G4TPedp23#jFew%%~TYBx;5EOy0$mQor)7gk?Mlq@gnm7x3XYZSs#BdZf*T1 zA8W8rhB1}o`;Z^;|0=fap>-LZ+6)e~Fm;M3p*6=4o=XrH3&w36$t49t2=9IsJ;FL0 z6{SV_mGZ=iR_s%cDiGOZ?V$0))=nG>7DB}?x)))866JEXw-jyH zem8R=SMai$t?5AO-teFiyN}2iBl-4^tU59}5On9j0NrBYuZ&)M1zG&B8gNnssMw;m z0;r12PPD?P-%ASp2v~HBF~*3ltSS2 zNPBIChq2@e2-b>7!vBYVsAHaTBg^iv<}$LWTXeQ2uEd-B!@?=}QPO9d!k)0ZaP!VH)4k_6GnCx>LVG`U9kyau8>N+Vg{tw4$P~$O^P(SyU1I{d@QnMXR zU^7SG!R=&&!xB2x;aBa0E{K`Ma?D#3H`%|YVKpc=3sz8T z3O5`R@6)q?HIlOP^UwPSw@eI>21m)VV19;3LB7Ll;pXStq>H*0Qa0nXH}ot~D;sn# zwvt>FVmxyx;3i-X5bi9RLH`s}IBsS|8Axjs0Jua6mBG(Z7~yyi{?xnWFgoW7CS!dM z>mk0>ns7e=QBAvlH36Sc8L&_I5oljyT(oFt^u2O_tT77Bw|Kna(IM$4s5GnNZ!#KZ zes6TiaP;O4j+4(}B2{~gCTf+MMW}Q`r7&7a?>MPu=q9*LYL;<+FPtMn`yu67OD=s@ zn{iE-A5iy}PcDTQa_TBYMd^eh|M0Xw;FJ1$;^a~aEF|Y)ze_dTXBLF!1SER9>&h|Jkt()4}_jH8=PkmpazcPp%af(dA;!Y9tP@fNj2Y6hgI?joeTL@NSE z?GXsppe6O=kb};#N^eY<^B}e{KE%A-R__OV#6lg)mTYO6)Qy09bzWg42_dE$`MH|M zD6am3fq8P%{u#d9WrMV=T7iaz8j^FCcs@g5!PB_b`OM@K?W-P-Dx(-HJ9fSZ>N`w- z?lzhvm=dk;u=;d8!C2TGudJQLZwwA@o+*$PGWUA-@_mcTB9k~sT|~O14atoU=#YP= z5TOgeHufhG<;|y)U+3Bp9!C{hGPk#uDyChN5XvQj1$|T^4gZ@^)sp*B@a23eP=0$M z>qz46uOIk93>YAhp#SL!@@3hg5rQFq%E$}3^!1c(Rx_WHd#I0iL@mCk|mc9ZGsoxLOQMhy2$F%yR@>3Vp-7&p!p;t_K4 zK6R}lWqN_>yfh6Jl$jvdsyN3y(hph1jvteYR9Z876JUU6li=pm+ZIyE6@|um0iQUw@nZ@o|^p0d4O^p8XAlLCmXv{A_~S3>kD#^qDGR zWcf`ufZ&|lNuT(}9+ZxjzZ|?nVX;&E8R*Lz0ry4fa{3}TLr11wX_g*;jg50@1NKH^ zfu*Ncj7p-+PrR-){je@0Qv`D&-x&jRSi()d+G{kJqUr0&k1+$qnHG5)2)JD$lggMq zbE3i1F{29u`d#vfiPYFTj0GnGWVM|0qMqA%EN~WFj}R|;6>jf6i+yR~nE*-X#47=O z^_EF4Anf*Gzi|c4o8rfRau)PGnr?a}j0xk+h?uTh(|+&JF_K>kZ#8I^k?-CN_t4wn zZe8t17gLkMIHl z4G{6Kgr@>3neGbz^6U-1#Yrwcq?G}KP*9qi7uQuW^iiP>U`5&!wrimfFgRYzknMCn zy)5l#_(7W48l$3r@QmCOEkWvW%#i^^9uYS#R|fqwxgDLT1TAab-B%i^aRU7ZU=4@> zb5O3cgo^Op>G9=HAstUmP^ zZPSo!%xScL^FZOwNv5055SP~hsF8P1f@=RCSmHZ5oHQ_@z`lGe;~N7( zle3`iwZR48Pr{3_J&%JKW^B6!FlXCMpGqabLr7!re6RQbIA&dI@QrIN{d(as*8MM7 zkn0uNUzldt&e*oaqGJUXV1%+pam{sxGG$ml#m2;c|L)K8(nh;P8v55t#o+|Dkx)C>!a~{ghv>Ul(!tbLDjarU7F*8LQLQx_5EkLRUe2FD260wR7&llXOIG9ZxsMwp?Wg z_&5)L)BAGO8Ud1zKo7Teds;b>(VQwM5re>WcLFC^Uus~vCV0;db?3jsN&9`VdCe5- zTiJoM^v1|FM;FR^P>71!crY^+OJ+3Y%P|GSdK>%^I@U@I1YHHrO28;ds6+C2(10ae zisXj&@^d;BbD?iwC8~J6FEL&FP3IO!soWNSB3iaKxKN9Pzx?`@JrrQNo5vFWyxl$T z5@<#PeClo&5Gen_{Imwgq<*aL6|FUFxL2MOFf1l$OeZOh(|+v}Gxqfm5C&of%(Xzx zT)kLJih!R_x2LhEb?eda`7MmO5z!hGH@sXd$7T-jjlz^K_Y5h^pC*66I&Y54GeppT znU-glVci>jx9^tD&>pFSfu_!gH68`Mz6Wh!Z`JX-FEEOF^`QN%Xo9Y2E78J>?8=)Wc7D|0@q^})rRh`v7XV9lHxF;T z(dTTtkds0gY^TG}5tLy!EoBy(jHdCZ;gvilbK1J90LD4+MlMzELVte~@5FDRz3x{= z!woS8y14>gWmOkb;?|5Ku#g(t~>6*6pF zFG3al5Z&TVxI>dykf(xqdNc+@R%H21a7HkQy^SkfzB5g380XTAqKmhON?dPoo^J!H zALzXq@QsNiwv6x`#IdY569+oAHVODAoYP!Q-(Uz^fkEl$WO|1nDvrc8yJxeRohMXg zb7ugZ<&zP||4J390U>R`5(znf0_OcpEpYQp16q@$1rvM|o)$%5F+|p-x6pO;bV)Gm_Yq;TwTt^j*6=Pu5 zErqEccip1|Wlf3xejpUY_A03>=WMHG(1tgeOS=%1T-S6G;Yc7mZM%$rhc z9TEUPSP!8gS^&tCXaW|0h~VbwwmZu83(rM#?(2GK8q8M8w){Z&)3gs;JFYQfi?hTw zphD=AFA2?Dqg}o2rmo_NM>cc#^l1W}E^& zg^ehoKtzC!^gQ2Owr4_cq;E>fRtPM>)H9H`rQ=hSdbW+C=Rzr2qF2fF6XQypNi}ko zZo;?iq6a~eKIva_3^KWB!)WK{t)SYGqz>7H13e|y2+oZfa_G=)PcAmQ-TyDz7pc;; zQY92p?4|p2)XScKCk-`}dpn5t#nd6hpQIRY@j{0?l+N2hS9c7Z(7p-)WXFdcLqvq$ab6wFc@QdC3J zzdod^j>l2#sJh^;b$;do8<S^!8Ic0WA>-MjUm}54lwN*YT3FY>NzS@HF>ERzg(7;aix@x|_zA zn?+w7Xg=7_9=^Q6y+Kl8bF;1D2ZNlVaJp(dNnBKakHApK9WGn6nbnVt6Yk+@`JUog z#l>a2v61iEEx97kCtNY;)BbDXX47BS49+k<*M5MLI2S6;8DamdI)Sx%nE;1oD*N?AxFNCkzaw6cGzVGoe}xMZm6Px#)J)@T8>q5 zuAz!J5266Ab+U`3K4%{I#sR=8JY6xU)G%WTl>fCdj2uu)0Rle*KL7#%4gj`&u~??* WM|d0-007d7ld}?1251%l0000w-TD^* delta 4779 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 F004_%7LWh{ diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.zip index 1b69e8e3d5d10acd501881ea862de234b4eb0006..bdc1f1bfde0efeae5123dd6c6535718d7ed543ef 100644 GIT binary patch delta 5776 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 Oldcj{28|W~0002a4<{c0 delta 4744 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 W6nsb$004_-lcyF^29y#20001Ok}kOb diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.zip index 5661f465dadda930fb010264e9ceb5900ddc3d93..1d2d91bad44b85a37a7aa75bd851d7d82e6e52ce 100644 GIT binary patch delta 5773 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 W_en?+004_-lcW|>29y#20002I=nxtJ diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.zip index cf4950769138dbebf8b0fcdd0d54a44606f0ce42..31888271991189c892d8e3c2786607e4e25f5c0b 100644 GIT binary patch delta 5803 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 delta 4736 zcmV-`5`XQXF8(DLP)h>@KL7#%4gevEmR8{E#H>IP004_-kr-Zo^+P_6+Z$mK0g+maPHU8a{$#J8tR~(IY@E2%ccj zs@aX#hm8p?Ix&>f*Sp1}Oihhd)}0gPc|?MOs(E*-Cl(G0mKQM#5Epx6ym+*YBHvaX z@`U|g;{rpQ;RMWoEN@A2c`r$KL9q2rha%dcx+v(@-s>D^#&@Ar3JcUTfY3Q4rP?`g zsfaMpy6BUE_l&PR31)v&bv64xmPc!!3);V8h(AH>TJ44y*&AzZLDAw>8pp-qm2p8K z#xM;iLtqv_z-9BmY535uH?N00xZ)z7!}oe03VzR{6uIetZawW)>38f#W3(ACR)#l- zQssKj%LUX}A zu_8cJ{vUwMcx}F}a34^<@gYNLgbSeN!RZ`+Vx~dQD|=f3Yg@n>eu_mVgh{ymFS`1s zs@~8M7JFNN^-3uRmbvEY64QpQ+rZ0i>7pDt3#b<3L^^1qoCHO*#&xV>V_oZMO%6OO z?td(pTunvz%rZFg`yYeZ%OmO) z9IY)sE1tD_Vr5TM`nya)0YAh|ZIt+LYG5mva^wlX3(C^^PtsNqR)^;NW|&lZ-@(r% zU^w-EhJ%U(ZIXKlq?~C?O>vdVeHx>lolRMF_&ZEw8qxDg{6(i3Y9x*BIScG+s^z6v zG~ivdmSo&pPk`0SQpyLageq*5(MS-{<{%w*-jW$71~|^>+U0JtMZR%sR?o_<avHrq188^~qP_8i9op%4*~n621qfN5CpqXk~+#&hU~|@5KU}( zlJ1~?$tEvT@5uNlk37wNs2#?O zXBG-$#@*#?z9#7e?^66rZQ2XqrQS?!PoYtr_YakVg+ZItbhAq3+>-Z0J#xH z881*R685la9A!UteS zHaNeHw0d{j+x-0idCH9^)CfBB!-(7M$cH1n!S7J#S$wV~sGPCOGQ<3>&hiR>V5^Yi zX}SH%q8lYF*KkYMAg6ZeBBthQmAfvB)K9w>Y3iT~r%Cdq1^P+NR?6z!PUF(Pa8I!B zfASa-o9f>9!vJuxCFZnij!1e1H?TVcp zjgq}}V&+IG+t?^`k7TwiR*9j1w1P)|KtyLHg&IY~g6yZLsCZJ43Di_Ys3(F zlKzKI_F3qhm?HZ7Ct#EKCdrc&cgq(u=ML%hDOtAoY=y(+In!h4GI`K?xyl%y`#Z&g zrU)T(=PZzs%a>(uC%|1^Sss#j?lq{H$yP~aN8g+ph}88Nfcz8^07=h z=#l9YFeS-#b?Zdj##qy62V&GuROrwhm2H8i2akAT!eov(m};4Ed*doey8u%(8(Gy3 zX^D`9kJlnZjoF^fsX?*EdEKHy4xp zH7cb@?pJe8@~)16Jcph8eHP2E8*&Bw&kS>2K^va`Wn1pl$+!mZFZ8t6INXanP)w0s z5!-9JnU_RtS}DSEfU#v|Q{KWCX^D#&p#{jwnK{f4_nNCo!nd6t}Q$>^!C&( zZ%AcoWc2?SFvO2GR!76qX1~SuYqiqf#2Mnr+kqO|W$%OHBQ#zD1N2W8CAf7U%uHDi zf_PAjb)?M<4_)DtdYWpR7BJ^(9($g|R-umei$_>=2)nGjQHal;_5Mn#8D*DY>eohQ z$kf&z_jz$khEk4ybWSx$+I?{Kt#`U3i(A6v0pR5U)gCVHBZcESB5{yE8e3v}@G9kl zAvYw`JMeQ?l9ka!H;relB-Fxy&d*C$C)Xo=o_Gbo*_bO&&O4x<1(EKCrM0%3OU>%( zLRX6KhENtu=(LaS^jP4t?0kj`!sj zt*&^?jr+E(RVYajjqKAK@JOT&xe!j1=ZVI7OvUW5sf=qDd*wIpyJu*?x*~B)1D&}e#oDG7 zK#sWsib!EX(HRI8)@VUsHg~|s8O>e zU4+2byI4$5+$iQW!Wn&}5MLPAD1+cz-DIm-pFMFQAgzQ(iP)KVtkM7Cy z4!FTmNjS5D-baJa+k*hcu%sdG3tlW<#DD{f1ib zvcvt3^xB{KOSgt+w#XqRMp16O-y{Ejt9z2GkX(}=$b;1uudEF(HRReqC^1oI z)F8?P&>-LP>1I3-RS>Mme{sU=t&VVAH~sx#=`M`8cGl~v65X?P z>}!OuhJ1n4^KG~(t9$yENG^H&Vb|O&mo0uO8K?|RrT!=bk;D)4x;`J>B(a5t=p%N2 zLJaispEOs4i8}+e3kKB$gkV@(jOIP7l-%z2CbsPBmZ#m}%{6qAXRTXw6WRcOy=B^7 z8DUp;i|+wJFkqjqOj2B0WF#ioOBoL17jD-K*!j%}%o_~`8)@?U!|eib^7L&yT*utA zdx9UN3sLt7P+eLaPl7tNuxqKfmJsxRGl+sr@W@sLsm4-jgucD(KGXcer~TydPaD-~ zr~A9b45>8vCgv~8((3v;x%nEEfArv3sK0bW= zMOK-VfSP=M>F=mlGXk4g%oE0$0Q?N*3kutBC&$N+e)4Il3RxKRzso@!9IG4I`=cCu*~Iu4j1o);TPWFaz5*38a_?`L3k|(Sk*S&0 zV>$&efJF*tiiJWO$@C!@X+%JOQ=CeGwfU1P>nH(;1r=EyecIdbn9T#OI4qRfCGQi2%dGLg!qkn}B? zKNiV`UaMrj$CXiesG-NOYF*RsmE&D>U+>tC zGU6KR)Uxia3An=oD9hO)KrQLO$W7o6nG+)XBHn@MuTjP`Y#i5B&}co|@a1&!weU!h z@uJ&LzNn|R*CZ+>7?SvZA6Z#vd__7$%cI&}`BpZ^ai^6sv295JwQJ~IC}17_CB!B> z{8%(NA^4*g*Q|5H$>j;zodE8GFhJCB&@NQ*!X#tyT4~aQ$CT=*n;|(ZC#s(qwGk3l zvC>PW3GhlEkgv_fjHaLCk}-=Bb#`#;P=Y~1Hv|)}F!T(;{ac8C%CL>q9a2ZkOWCCB z|FK{S7eG;lr?~ouZm>a>Yih5Nt(H~xsx103^Mnu{#{Vvj{h1BaSbN-`n7?)j(HLko z^p{32p<=)*BnP0~t|gzf*`h}Fct1PmX zVV<#75LQEi1Cpz&5|> zv`negjo0OWDD!_53>cAn$i!vxc3|>ZX%S9)&tQFw%%L!a*bE1crPB$Llja{==UVxN#=*9SAN~=1ML}Ch#j%w1~NaNqQg6h%k$oLPa z`f3@!_TX%-9S`y^cJx;_m!pI6e3#^3$}{Orz$&PJ68K#^(RqUhZyirJ3Rm5L)&N!) zTCgO`<|t%MiS#JSVMaMkWkEbz1%m}Y2Q9V2jE=+MA_TMJd5J!1d`1X_X;28&CDSMB z;wr5=voL-d!8R*rB+x&Mhhg%6Eo9w@uT`Eshc|J?V76onoPZZnBX!h}@GRr;{au*% z_#Kyj*}d+ocZ^F%SB2sD({l>6C$JV*Z^)`bdjWMKKYm z9@)`?6`DN{DhEQOC zpaxxw2UUw%%)E{)g}0kU`thOp{}6+ZwSr4U^hf_1atz+_Xr6(K6W$?1>hTBv=Daq+#Hk> zLkU*ND6Ng}AA?fDftI!>k^baR2K*O)Ed3wRNG5)IshT54>c>Y86u4);^yQmod9#91 zQm>CfA%sI+C3RN#CD_gT1BkN7_)lVW56Dt#d44Js85Okww+*B25};HrgZ)W@0ddaXwsT(` zNZGav`ZI-ejAV+mj1l-tNq91*n5yU;1UL-9VnqdL%hJvw?98hPOYYIw^7>3(_Xph%?*McYyX$iC5%FzY zM4#@L1_**#$I~H9#PXb2Pkuw4SO4bW-5yX&0Rle*KL7#%4gevEmR8{E#H>IP004_- OlgSoR28@KL7#%4gj}(u~;}@Mp;G{007d7001tNy%I5zOe%lzM-PRi zm0nlZdjJq|?-l5q5W}VAK!X$~yhYN!b#(5g+&e%nCd!7EfUFi6AerXVhG8zww5+rr zt8@}M{ABq+?ls#>N#jh&9{$PK8;!81v1t>n2v=}L0%u>0kb3$y*mDmUlDKEkW?V)l zgu7*><==ZNk{>&!gUD&;7Y~0(vA!EKFGWbH*v&bkOJgl*Ct(KT8bWe^t>ddr&}J9= zT|B98TM8u@c%~@i1F zzcR|_Ka7K$fYYRM@ zBoJZ|q$jwF$9_tbs6k7`**6Kx%;Zwlp zx_Z8zu^~ZLX$#41KMc9}El+0AB#;x%P6=WgOsnOI+*DHZJoYXg3H4}<{9e2#y#ffq z6w==6*B?K|9vk~1A?PIyV;8;63~q0c8)o1~f|C3DI>{BiXYzmZO#q>`Of=Isgt&KR zM`ge_)|MvM9bX=DkP5rfpk>k72gh!cOv*oOAA9G5r-4JC>-ckVrwEg6nzCm+&NVT` zGNX>AW<1(#?7|d2>pv|dAgNx0t{RB09F?sW4U*wPm<}YpDXuQ#9SZhw!yNIDZwd)@V`7vY*Dl^7oBLnSy|Z?naCq@W*(o|^;* zwX8TYl8&Ee8Kdr&G(XrUZl`JpXxxkson~Z&g%mT)Otae${3J$P4=NX*5a*zr@CDX8q>{I`E_ZiM zqXXw*t+z)~j}baOh>$VJ4L2`1fWrS5_=$hl6}ojEW6zT%bXEVS+6Y)&PzTCdm2|mp za!h}Y@>mRl=Yjb`y5;(uW!fzqPD8>u=Uf3tS;yc0XvB9AkE$%gt0dLRWu<&*5!`7C zHbuMNx5&9wcL<}MCbVwUw{A4A6Z7As>R?qx0&9Xc_7)rL@*;6q|MKQtkNL;fjSn!) z`FHs_CkWY9aKD1-HvRqFzK#7jsq6|1Y%6~*d&1oxSI5t8&BaAKE@te2*Ho>KqPt%W z(}>oG++OOROq?%rufG_pJFqiotxU4P*a_+_MPi+<7MZb6zI0(1wGR0DE+dWt9RWG> zEDxs4FHEAP0YmZ~nZHc3%OZYITAvi>T){U2$|PAOqmf(!3=t#uFIi3eu`jF5JsyAJ zO*(<17a?a5+sVV2#@gS_OT|pzQ9=wQEY(YP2_#yPs^xaPUTb8Kt;p3n*pp@w3Ld!T z;X{8LyGg4vn0O`Gr>DPQ-|ED`a+9PB=2H2Bn{amT@WJMTsi*w|+A8@`jR<1XFg%$u zzz>0~K<-(yenjYgyJPOO$P>^J7wmtgSAKD%{1W-0PczSG+I(VuX-w@ar)$G)=^i&+ z-cE&3;pUc3yjjycP*!53(_ScW^S;aTDn}F_s#m%~ZX%7qNM-(6u9 zVcCyW--_32_A2a75tW1;fj7|Y~>I8)^1K*B!ufuDQzTb``kK6HU6$<#}}Gs}OJwH8)rZ(UVP z(Y+YB$bB96L9L?}1E7z=e_QGAle3}w+(y1N&wH~pGX!qoD7Pa=YAHUsWK%*yVS4K& z=WQ=q^-twUjY8O!fh14zcL^lR!nkK=Q*B)lTtWh?Z31RaugN0=%1OWqFbhm|ED*0N zR}N$c&_@YM!1`jBu@Qe!yfMdPrY_<-NC@|l$yhOGMHcN{8bsl~PBRmN2#y|3zG)=d ze;2i2?`QIs*yNhor0G+NEDVo*Aw>dJA?~b~IJ2_S4OXRR{`LUp&ET?jI1n2rem{^mfIOOBC=gsYg-Iss4Rla)aod=<$0MVd9(95(rIcI~a#T2s*sJaQTe`UlLn5 zS}g_R*9skDXz*(flFE#J(HbJGN$V~4=a@l_X#y4d7RI1h|tjVYB;!P`} zo00}qFxooR)KcsP<44p->vXYGsn0i=hMbvhbc^uKSSKATHxo7P-{;>*anZES@mHbT z*>4o-x91%V?Uh}<gdG_P*hO-l48$-wyyj7PQi`!x%E!X9ViU8Cr@^TNu za}Vqz$eL}vwuIkEv@(zJQNDbm(l4xyeO)xuxlDyKo;(s7xE(a8{qY+BD-4tb4@Gev zqp3@aRQ^cl@eX2+LSA-2*pL7|DbK$NN2j-USIB>>eTvJ;qz=1A_wA#^Zp3#W)a=$g zNZHMD#+>mdY{GWY;KQ&Y*A$3?hfnFsY~pYeyl(Fm_WHVA zyV!qoCzO&~_pkv?;b}J%bT0ClAa0w0;e>hL?B`vLC>wjZc?_PO+Ww0W992JkY$Vou zr0Vwu-ublk>Ecc>1w6B+QT-nuD~r;u2tJ~%zB-Xvex~4bNV0CHx;AgK%Z5u&cY3vg z?X-^Z&NM14ez4SQH89U@d){|qM-pC=Z$MTg_UC+Cx zJ)&04(XKp>ja=lMT$b+4!?RV_!eI5AzeZf5dyEEIFsA-m5oQvfD`QRm1bY?R-4lf$ zm5nB8%g+1`#8PeYz7U)IKrsdC&TwTUgfNe+l(9@bAfe%@^qFIetdDJ?O`uvYTql1t zN&ezH)PNdZ<#9I zwhN!CUnc@2YsJ6`X#)9=`Bow2!;ePV(VB9ne7JjiB4@iV;+UW*Lal#BwrK|9 z!>0FR!H1Gw|GsGhz_*_9SC)+oxZ7F&hK-7CI)+eUwNN37GNde5|m74BX02Vol+|4xMv|5aiQTL4lNqv1h zn#}3;%`dHU2JOb9;WfeL1~-3~ftM7n-edP}TuPl%CU2D0NpAA@(7XHKP%mRN(1DS_ zGDO;Rf$oz;s6TLL&IQyDc5Gu#_)nhll`W30JQX)y{C70#KU$eZjwn<5$77tHzVG7*YYf`=fuQAa&_Xzd*3X zNNAlG&@$K0Rj}#!nZi9(MTLP`94L$1^STUd&FR3Swh*QFJ|#j*-2Q^q#&ns;kQ5;o zr6ozqE=Y-ZqfHFkKFt?crC497$!9?G2tr(l;Yl~z%;u7`J5NUWKoT7ut^g^SS%vf`NHKNfxfhjt`)_+7m?gau z+vu_-=Pn~fbP!WkXTYghI1^WVvRm`FELT>+G>_*ZfS>SPxix=?9SPDv9SRCqikOVP znq@m;<%xsTSmD+v^++O))Gk1}y&LpK8g!n*w=g(G_%LW_OcvU-kdh{NDtY~qK0L*1ru!3bjF#UIHwKzMt?cCik(!NZr6!Kf% zeXyR2AU8&ZHOhZ#uI8LdT^#XECmW7Tpdgaq;mB`Jy&sQ|>I6hr}KGLvS$onqD^ej9i!Xmjc zs!SW)DALASPH8_jsJ|{^8?Y4Y0^lUAZrV2V#;}~X@@3X7j}ESiib;(PxOv2WqsEy9m$@_t<_X~Kw)qEyr3cD2Mx=7O^IKf(}gul*kjX#3IO->X5xm@ zmO=s~{Pj`a<8pLGtHq_=E(syvpb_@Qsako#Hr!&gWYCL)17XK<4Fb3&h*Ra%pTEO< z_V7OrTMRE^h~hN`b_*Os!RsSgZv3o0Q-2bkSZ05kVLfJv7aogGvPT*o5YqR!t86zI z!cf^y!yK0vo}9x&;;?ruYyW{c_Wj~>g7uoqXM&zxMHa^?`~rC(DQ9a^4oEpRbr0n} z>6L7)^FyeIyYqH*4ixJ2nn@LIoyvWYi65Wm_xXY*Rr~1vojd;tT~%wpfmq}&cL6QS z3?P3gOa~^(Nz)9h$znHZnv(&(c&HODhgMM~K@>iuZ5SA>=bK~?o@fu+h@>~AwpP(6zL{A=|Z#tEZSj8uA z+d2^!5FhEsBa8aNejcyJVvG~;HJChef-St&Z2IW(DBge~epQq!nL4jG_?|Bh7z2OP z3LI(UCuC<`=jJ6{!-Fev;tS6w%w}f7Rvh|_Z9Ap5tCc|NXHSi@w|1qBg`>V`)@9?e znNTi9J7;BY{$boC8Ww%iN|VWjhd1Xl zE=0GgIohLF`V82~tn-vEDg8xLIP1bS(Ol1D%!}DkQvK|d$A8aN-f(|b&RISBM5qfD zjSLUwKVYfpVg8AA?(=A8e|8Nn4{VF8b82RBlw9)VReaR^8hkUtGVN_%HI2k*(u(Ou zW=I8-6?BbW@iMRPVOj=Qt)gKI$=_vxp!bqKrTHwWfc7L|`9L-!v=3K*0^$FXV23S? zVYhkVi>Rmo(2U+)guQ>3a^JNOMz(4W*(c-c@Ij+0NN2i|KNKzXR>U0@%u!%Rq0-q_ z{@*ofKF_Ly8co`+eGdey&`vXRN@@ld5t#*8Ig%BADZ_f~{R+?S!GxX9^!7 zBespFKkgw?OWf5Bgg3+XB3^J&Jly@njM%s<|dC@a~W+463L_W+tJmP-JA z_5mNnDrbm!VDnK3Lg(kn!6KN_lO@DmG|fk6tY7o#+Awf3wBiFdJph zG;O?^f>r|hjj$rNjI!VU4uWMH_t|)(pH2Vw&Az-)O928u13v%)01g1ReX&?LU`AO+ S761U!iIc1nQw0_P0002ObSt?4 delta 4748 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 aiI!G#kGXe75&!^;W|OQIQw0(L0002H5HMf> diff --git a/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.zip b/tests/e2e/solc_parsing/test_data/compile/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.zip index d574a7cb8486ac0764de875611abf38c434d2514..4c6db0a4249394f7d98511a9c3bae9f896c1953c 100644 GIT binary patch delta 5792 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\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "test_decode_struct_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.json index 070b687bd..b040e9ab4 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.11-compact.json @@ -2,6 +2,7 @@ "I": {}, "C": { "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "test_decode_struct_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.json index 070b687bd..b040e9ab4 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.12-compact.json @@ -2,6 +2,7 @@ "I": {}, "C": { "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "test_decode_struct_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.json index 070b687bd..b040e9ab4 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.13-compact.json @@ -2,6 +2,7 @@ "I": {}, "C": { "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "test_decode_struct_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.json index 070b687bd..b040e9ab4 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.14-compact.json @@ -2,6 +2,7 @@ "I": {}, "C": { "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "test_decode_struct_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.json index 070b687bd..b040e9ab4 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.15-compact.json @@ -2,6 +2,7 @@ "I": {}, "C": { "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "test_decode_struct_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.json b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.json index 070b687bd..b040e9ab4 100644 --- a/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.json +++ b/tests/e2e/solc_parsing/test_data/expected/user_defined_value_type/abi-decode-fixed-array.sol-0.8.8-compact.json @@ -2,6 +2,7 @@ "I": {}, "C": { "test_decode_interface_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", - "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + "test_decode_enum_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "test_decode_struct_array(bytes)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/e2e/solc_parsing/test_data/user_defined_value_type/abi-decode-fixed-array.sol b/tests/e2e/solc_parsing/test_data/user_defined_value_type/abi-decode-fixed-array.sol index 14a59b5a2..d5bddddc2 100644 --- a/tests/e2e/solc_parsing/test_data/user_defined_value_type/abi-decode-fixed-array.sol +++ b/tests/e2e/solc_parsing/test_data/user_defined_value_type/abi-decode-fixed-array.sol @@ -1,10 +1,11 @@ interface I {} enum A {a,b} - +struct S {uint256 a;} contract C { I[6] interfaceArray; A[6] enumArray; + function test_decode_interface_array(bytes memory data) public { interfaceArray = abi.decode(data, (I[6])); } @@ -13,4 +14,8 @@ contract C { enumArray = abi.decode(data, (A[6])); } + function test_decode_struct_array(bytes memory data) public { + S[6] memory structArray = abi.decode(data, (S[6])); + } + } From 40578aee4cdf4a63ed00c06722753f7982040778 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 22:40:36 +0000 Subject: [PATCH 28/32] --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afead5336..820223cbe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,7 @@ jobs: - name: Set up nix if: matrix.type == 'dapp' - uses: cachix/install-nix-action@v26 + uses: cachix/install-nix-action@V27 - name: Set up cachix if: matrix.type == 'dapp' From 599edf78d8fe63f8c77ef7bc67f0525a1bc35a77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 22:40:43 +0000 Subject: [PATCH 29/32] --- updated-dependencies: - dependency-name: cachix/cachix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afead5336..0c0682ae4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: - name: Set up cachix if: matrix.type == 'dapp' - uses: cachix/cachix-action@v14 + uses: cachix/cachix-action@v15 with: name: dapp From 221cfc69ce628db819c56f1ece4c4e82867bc386 Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Mon, 3 Jun 2024 14:48:07 -0500 Subject: [PATCH 30/32] chore: remove unused scripts --- scripts/ci_test.sh | 84 -------------------------------------------- scripts/json_diff.py | 27 -------------- 2 files changed, 111 deletions(-) delete mode 100755 scripts/ci_test.sh delete mode 100644 scripts/json_diff.py diff --git a/scripts/ci_test.sh b/scripts/ci_test.sh deleted file mode 100755 index 6696a4e89..000000000 --- a/scripts/ci_test.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env bash - -### Test Detectors - -DIR="$(cd "$(dirname "$0")" && pwd)" - -CURRENT_PATH=$(pwd) -TRAVIS_PATH='/home/travis/build/crytic/slither' - -# test_slither file.sol detectors -test_slither(){ - - expected="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.json" - - # run slither detector on input file and save output as json - if ! slither "$1" --solc-disable-warnings --detect "$2" --json "$DIR/tmp-test.json"; - then - echo "Slither crashed" - exit 255 - fi - - if [ ! -f "$DIR/tmp-test.json" ]; then - echo "" - echo "Missing generated file" - echo "" - exit 1 - fi - sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i - result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json") - - rm "$DIR/tmp-test.json" - if [ "$result" != "{}" ]; then - echo "" - echo "failed test of file: $1, detector: $2" - echo "" - echo "$result" - echo "" - exit 1 - fi - - # run slither detector on input file and save output as json - if ! slither "$1" --solc-disable-warnings --detect "$2" --legacy-ast --json "$DIR/tmp-test.json"; - then - echo "Slither crashed" - exit 255 - fi - - if [ ! -f "$DIR/tmp-test.json" ]; then - echo "" - echo "Missing generated file" - echo "" - exit 1 - fi - - sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$DIR/tmp-test.json" -i - result=$(python "$DIR/json_diff.py" "$expected" "$DIR/tmp-test.json") - - rm "$DIR/tmp-test.json" - if [ "$result" != "{}" ]; then - echo "" - echo "failed test of file: $1, detector: $2" - echo "" - echo "$result" - echo "" - exit 1 - fi -} - -# generate_expected_json file.sol detectors -generate_expected_json(){ - # generate output filename - # e.g. file: uninitialized.sol detector: uninitialized-state - # ---> uninitialized.uninitialized-state.json - output_filename="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.json" - output_filename_txt="$DIR/../tests/expected_json/$(basename "$1" .sol).$2.txt" - - # run slither detector on input file and save output as json - slither "$1" --solc-disable-warnings --detect "$2" --json "$output_filename" > "$output_filename_txt" 2>&1 - - - sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename" -i - sed "s|$CURRENT_PATH|$TRAVIS_PATH|g" "$output_filename_txt" -i -} - diff --git a/scripts/json_diff.py b/scripts/json_diff.py deleted file mode 100644 index 9422f6b8d..000000000 --- a/scripts/json_diff.py +++ /dev/null @@ -1,27 +0,0 @@ -import sys -import json -from pprint import pprint -from deepdiff import DeepDiff # pip install deepdiff - - -if len(sys.argv) != 3: - print("Usage: python json_diff.py 1.json 2.json") - sys.exit(-1) - -with open(sys.argv[1], encoding="utf8") as f: - d1 = json.load(f) - -with open(sys.argv[2], encoding="utf8") as f: - d2 = json.load(f) - - -# Remove description field to allow non deterministic print -for elem in d1: - if "description" in elem: - del elem["description"] -for elem in d2: - if "description" in elem: - del elem["description"] - - -pprint(DeepDiff(d1, d2, ignore_order=True, verbose_level=2)) From ecf8b24f09567b3729aea73aaea6650629cb6ddc Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 4 Jun 2024 15:29:54 -0500 Subject: [PATCH 31/32] lint --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 4d9e1d10e..1d05f02eb 100644 --- a/README.md +++ b/README.md @@ -288,24 +288,24 @@ Slither is licensed and distributed under the AGPLv3 license. [Contact us](mailt Title | Usage | Authors | Venue | Code --- | --- | --- | --- | --- -[ReJection: A AST-Based Reentrancy Vulnerability Detection Method](https://www.researchgate.net/publication/339354823_ReJection_A_AST-Based_Reentrancy_Vulnerability_Detection_Method) | AST-based analysis built on top of Slither | Rui Ma, Zefeng Jian, Guangyuan Chen, Ke Ma, Yujia Chen | CTCIS 19 +[ReJection: A AST-Based Reentrancy Vulnerability Detection Method](https://www.researchgate.net/publication/339354823_ReJection_A_AST-Based_Reentrancy_Vulnerability_Detection_Method) | AST-based analysis built on top of Slither | Rui Ma, Zefeng Jian, Guangyuan Chen, Ke Ma, Yujia Chen | CTCIS 19 | - [MPro: Combining Static and Symbolic Analysis forScalable Testing of Smart Contract](https://arxiv.org/pdf/1911.00570.pdf) | Leverage data dependency through Slither | William Zhang, Sebastian Banescu, Leodardo Pasos, Steven Stewart, Vijay Ganesh | ISSRE 2019 | [MPro](https://github.com/QuanZhang-William/M-Pro) -[ETHPLOIT: From Fuzzing to Efficient Exploit Generation against Smart Contracts](https://wcventure.github.io/FuzzingPaper/Paper/SANER20_ETHPLOIT.pdf) | Leverage data dependency through Slither | Qingzhao Zhang, Yizhuo Wang, Juanru Li, Siqi Ma | SANER 20 -[Verification of Ethereum Smart Contracts: A Model Checking Approach](http://www.ijmlc.org/vol10/977-AM0059.pdf) | Symbolic execution built on top of Slither’s CFG | Tam Bang, Hoang H Nguyen, Dung Nguyen, Toan Trieu, Tho Quan | IJMLC 20 +[ETHPLOIT: From Fuzzing to Efficient Exploit Generation against Smart Contracts](https://wcventure.github.io/FuzzingPaper/Paper/SANER20_ETHPLOIT.pdf) | Leverage data dependency through Slither | Qingzhao Zhang, Yizhuo Wang, Juanru Li, Siqi Ma | SANER 20 | - +[Verification of Ethereum Smart Contracts: A Model Checking Approach](http://www.ijmlc.org/vol10/977-AM0059.pdf) | Symbolic execution built on top of Slither’s CFG | Tam Bang, Hoang H Nguyen, Dung Nguyen, Toan Trieu, Tho Quan | IJMLC 20 | - [Smart Contract Repair](https://arxiv.org/pdf/1912.05823.pdf) | Rely on Slither’s vulnerabilities detectors | Xiao Liang Yu, Omar Al-Bataineh, David Lo, Abhik Roychoudhury | TOSEM 20 | [SCRepair](https://github.com/xiaoly8/SCRepair/) -[Demystifying Loops in Smart Contracts](https://www.microsoft.com/en-us/research/uploads/prod/2020/08/loops_solidity__camera_ready-5f3fec3f15c69.pdf) | Leverage data dependency through Slither | Ben Mariano, Yanju Chen, Yu Feng, Shuvendu Lahiri, Isil Dillig | ASE 20 -[Trace-Based Dynamic Gas Estimation of Loops in Smart Contracts](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9268144) | Use Slither’s CFG to detect loops | Chunmiao Li, Shijie Nie, Yang Cao, Yijun Yu, Zhenjiang Hu | IEEE Open J. Comput. Soc. 1 (2020) +[Demystifying Loops in Smart Contracts](https://www.microsoft.com/en-us/research/uploads/prod/2020/08/loops_solidity__camera_ready-5f3fec3f15c69.pdf) | Leverage data dependency through Slither | Ben Mariano, Yanju Chen, Yu Feng, Shuvendu Lahiri, Isil Dillig | ASE 20 | - +[Trace-Based Dynamic Gas Estimation of Loops in Smart Contracts](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9268144) | Use Slither’s CFG to detect loops | Chunmiao Li, Shijie Nie, Yang Cao, Yijun Yu, Zhenjiang Hu | IEEE Open J. Comput. Soc. 1 (2020) | - [SAILFISH: Vetting Smart Contract State-Inconsistency Bugs in Seconds](https://arxiv.org/pdf/2104.08638.pdf) | Rely on SlithIR to build a *storage dependency graph* | Priyanka Bose, Dipanjan Das, Yanju Chen, Yu Feng, Christopher Kruegel, and Giovanni Vigna | S&P 22 | [Sailfish](https://github.com/ucsb-seclab/sailfish) -[SolType: Refinement Types for Arithmetic Overflow in Solidity](https://arxiv.org/abs/2110.00677) | Use Slither as frontend to build refinement type system | Bryan Tan, Benjamin Mariano, Shuvendu K. Lahiri, Isil Dillig, Yu Feng | POPL 22 -[Do Not Rug on Me: Leveraging Machine Learning Techniques for Automated Scam Detection](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract tokens' features (mintable, pausable, ..) | Mazorra, Bruno, Victor Adan, and Vanesa Daza | Mathematics 10.6 (2022) +[SolType: Refinement Types for Arithmetic Overflow in Solidity](https://arxiv.org/abs/2110.00677) | Use Slither as frontend to build refinement type system | Bryan Tan, Benjamin Mariano, Shuvendu K. Lahiri, Isil Dillig, Yu Feng | POPL 22 | - +[Do Not Rug on Me: Leveraging Machine Learning Techniques for Automated Scam Detection](https://www.mdpi.com/2227-7390/10/6/949) | Use Slither to extract tokens' features (mintable, pausable, ..) | Mazorra, Bruno, Victor Adan, and Vanesa Daza | Mathematics 10.6 (2022)| - [MANDO: Multi-Level Heterogeneous Graph Embeddings for Fine-Grained Detection of Smart Contract Vulnerabilities](https://arxiv.org/abs/2208.13252) | Use Slither to extract the CFG and call graph | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang| IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | [ge-sc](https://github.com/MANDO-Project/ge-sc) [Automated Auditing of Price Gouging TOD Vulnerabilities in Smart Contracts](https://www.cs.toronto.edu/~fanl/papers/price-icbc22.pdf) | Use Slither to extract the CFG and data dependencies| Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | [Smart-Contract-Repair](https://github.com/Veneris-Group/TOD-Location-Rectification) [Modeling and Enforcing Access Control Policies for Smart Contracts](https://publikationen.bibliothek.kit.edu/1000152805/151859658) | Extend Slither's data dependencies | Jan-Philipp Toberg, Jonas Schiffl, Frederik Reiche, Bernhard Beckert, Robert Heinrich, Ralf Reussner | IEEE International Conference on Decentralized Applications and Infrastructures (DAPPS), 2022 | [SolidityAccessControlEnforcement](https://github.com/KASTEL-CSSDA/SolidityAccessControlEnforcement) -[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 -[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 -[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 -[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 -[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 +[Smart Contract Vulnerability Detection Based on Deep Learning and Multimodal Decision Fusion](https://www.mdpi.com/1424-8220/23/16/7246) | Use Slither to extract the CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 | - +[Semantic-enriched Code Knowledge Graph to Reveal Unknowns in Smart Contract Code Reuse](https://www.researchgate.net/profile/Qing-Huang-26/publication/370638129_Semantic-enriched_Code_Knowledge_Graph_to_Reveal_Unknowns_in_Smart_Contract_Code_Reuse/links/645b7b8639c408339b3a54da/Semantic-Enriched-Code-Knowledge-Graph-to-Reveal-Unknowns-in-Smart-Contract-Code-Reuse.pdf) | Use Slither to extract the code features (CFG, function, parameters types, ..) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 | - +[Smart Contract Parallel Execution with Fine-Grained State Accesses](https://personal.ntu.edu.sg/yi_li/files/Qi2023SCP.pdf) | Use Slither to build state access graphs | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | - +[Bad Apples: Understanding the Centralized Security Risks in Decentralized Ecosystems](https://diaowenrui.github.io/paper/www23-yan.pdf) | Implement an internal analysis on top of Slither | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | - +[Identifying Vulnerabilities in Smart Contracts using Interval Analysis](https://arxiv.org/pdf/2309.13805.pdf) | Create 4 detectors on top of Slither | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | - Storage State Analysis and Extraction of Ethereum Blockchain Smart Contracts (no PDF in open access) | Rely on Slither's CFG and AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | [SmartMuv](https://github.com/WaizKhan7/SmartMuv) If you are using Slither on an academic work, consider applying to the [Crytic $10k Research Prize](https://blog.trailofbits.com/2019/11/13/announcing-the-crytic-10k-research-prize/). From b9a3ea6189c374efc2c4508cdb25c3a067cb7b9f Mon Sep 17 00:00:00 2001 From: alpharush <0xalpharush@protonmail.com> Date: Tue, 4 Jun 2024 18:29:09 -0500 Subject: [PATCH 32/32] remove similar-names bc it's slow (#2469) --- slither/detectors/all_detectors.py | 1 - .../detectors/variables/similar_variables.py | 106 ------------------ ...ection_0_4_25_similar_variables_sol__0.txt | 2 - ...ection_0_5_16_similar_variables_sol__0.txt | 2 - ...ection_0_6_11_similar_variables_sol__0.txt | 2 - ...tection_0_7_6_similar_variables_sol__0.txt | 2 - .../0.4.25/similar_variables.sol | 7 -- .../0.4.25/similar_variables.sol-0.4.25.zip | Bin 1788 -> 0 bytes .../0.5.16/similar_variables.sol | 7 -- .../0.5.16/similar_variables.sol-0.5.16.zip | Bin 1787 -> 0 bytes .../0.6.11/similar_variables.sol | 7 -- .../0.6.11/similar_variables.sol-0.6.11.zip | Bin 1811 -> 0 bytes .../similar-names/0.7.6/similar_variables.sol | 7 -- .../0.7.6/similar_variables.sol-0.7.6.zip | Bin 1753 -> 0 bytes tests/e2e/detectors/test_detectors.py | 20 ---- 15 files changed, 163 deletions(-) delete mode 100644 slither/detectors/variables/similar_variables.py delete mode 100644 tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_4_25_similar_variables_sol__0.txt delete mode 100644 tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_5_16_similar_variables_sol__0.txt delete mode 100644 tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_6_11_similar_variables_sol__0.txt delete mode 100644 tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_7_6_similar_variables_sol__0.txt delete mode 100644 tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol delete mode 100644 tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol-0.4.25.zip delete mode 100644 tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol delete mode 100644 tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol-0.5.16.zip delete mode 100644 tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol delete mode 100644 tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol-0.6.11.zip delete mode 100644 tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol delete mode 100644 tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol-0.7.6.zip diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index ff1c352c3..7c5484431 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -57,7 +57,6 @@ from .slither.name_reused import NameReused from .functions.unimplemented import UnimplementedFunctionDetection from .statements.mapping_deletion import MappingDeletionDetection from .statements.array_length_assignment import ArrayLengthAssignment -from .variables.similar_variables import SimilarVarsDetection from .variables.function_init_state_variables import FunctionInitializedState from .statements.redundant_statements import RedundantStatements from .operations.bad_prng import BadPRNG diff --git a/slither/detectors/variables/similar_variables.py b/slither/detectors/variables/similar_variables.py deleted file mode 100644 index dccaf09c4..000000000 --- a/slither/detectors/variables/similar_variables.py +++ /dev/null @@ -1,106 +0,0 @@ -""" -Check for state variables too similar -Do not check contract inheritance -""" -import difflib -from typing import List, Set, Tuple - -from slither.core.declarations.contract import Contract -from slither.core.variables.local_variable import LocalVariable -from slither.detectors.abstract_detector import ( - AbstractDetector, - DetectorClassification, - DETECTOR_INFO, -) -from slither.utils.output import Output - - -class SimilarVarsDetection(AbstractDetector): - """ - Variable similar detector - """ - - ARGUMENT = "similar-names" - HELP = "Variable names are too similar" - IMPACT = DetectorClassification.INFORMATIONAL - CONFIDENCE = DetectorClassification.MEDIUM - - WIKI = ( - "https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar" - ) - - WIKI_TITLE = "Variable names too similar" - WIKI_DESCRIPTION = "Detect variables with names that are too similar." - WIKI_EXPLOIT_SCENARIO = "Bob uses several variables with similar names. As a result, his code is difficult to review." - WIKI_RECOMMENDATION = "Prevent variables from having similar names." - - @staticmethod - def similar(seq1: str, seq2: str) -> bool: - """Test the name similarity - - Two name are similar if difflib.SequenceMatcher on the lowercase - version of the name is greater than 0.90 - See: https://docs.python.org/2/library/difflib.html - Args: - seq1 (str): first name - seq2 (str): second name - Returns: - bool: true if names are similar - """ - val = difflib.SequenceMatcher(a=seq1, b=seq2).ratio() - ret = val > 0.90 - return ret - - @staticmethod - def detect_sim(contract: Contract) -> Set[Tuple[LocalVariable, LocalVariable]]: - """Detect variables with similar name - - Returns: - bool: true if variables have similar name - """ - all_var = [x.variables for x in contract.functions] - all_var = [x for l in all_var for x in l] - - contract_var = contract.variables - - all_var = list(set(all_var + contract_var)) - - ret = set() - # pylint: disable=consider-using-enumerate - for i in range(len(all_var)): - v1 = all_var[i] - _v1_name_lower = v1.name.lower() - for j in range(i, len(all_var)): - v2 = all_var[j] - if len(v1.name) != len(v2.name): - continue - _v2_name_lower = v2.name.lower() - if _v1_name_lower != _v2_name_lower: - if SimilarVarsDetection.similar(_v1_name_lower, _v2_name_lower): - ret.add((v1, v2)) - - return ret - - def _detect(self) -> List[Output]: - """Detect similar variables name - - Returns: - list: {'vuln', 'filename,'contract','vars'} - """ - results = [] - for c in self.contracts: - allVars = self.detect_sim(c) - if allVars: - for (v1, v2) in sorted(allVars, key=lambda x: (x[0].name, x[1].name)): - v_left = v1 if v1.name < v2.name else v2 - v_right = v2 if v_left == v1 else v1 - info: DETECTOR_INFO = [ - "Variable ", - v_left, - " is too similar to ", - v_right, - "\n", - ] - json = self.generate_result(info) - results.append(json) - return results diff --git a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_4_25_similar_variables_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_4_25_similar_variables_sol__0.txt deleted file mode 100644 index 7f6fa4da1..000000000 --- a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_4_25_similar_variables_sol__0.txt +++ /dev/null @@ -1,2 +0,0 @@ -Variable Similar.f().testVariable (tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol#3) is too similar to Similar.f().textVariable (tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol#4) - diff --git a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_5_16_similar_variables_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_5_16_similar_variables_sol__0.txt deleted file mode 100644 index 70b5c329b..000000000 --- a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_5_16_similar_variables_sol__0.txt +++ /dev/null @@ -1,2 +0,0 @@ -Variable Similar.f().testVariable (tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol#3) is too similar to Similar.f().textVariable (tests/e2e/detectors/test_data/similar-names/0.5.16/similar_variables.sol#4) - diff --git a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_6_11_similar_variables_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_6_11_similar_variables_sol__0.txt deleted file mode 100644 index efb92b5aa..000000000 --- a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_6_11_similar_variables_sol__0.txt +++ /dev/null @@ -1,2 +0,0 @@ -Variable Similar.f().testVariable (tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol#3) is too similar to Similar.f().textVariable (tests/e2e/detectors/test_data/similar-names/0.6.11/similar_variables.sol#4) - diff --git a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_7_6_similar_variables_sol__0.txt b/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_7_6_similar_variables_sol__0.txt deleted file mode 100644 index 67d482328..000000000 --- a/tests/e2e/detectors/snapshots/detectors__detector_SimilarVarsDetection_0_7_6_similar_variables_sol__0.txt +++ /dev/null @@ -1,2 +0,0 @@ -Variable Similar.f().testVariable (tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol#3) is too similar to Similar.f().textVariable (tests/e2e/detectors/test_data/similar-names/0.7.6/similar_variables.sol#4) - diff --git a/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol b/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol deleted file mode 100644 index 57f969867..000000000 --- a/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol +++ /dev/null @@ -1,7 +0,0 @@ -contract Similar { - function f() public returns (uint) { - uint testVariable = 1; - uint textVariable = 2; - return testVariable + textVariable; - } -} \ No newline at end of file diff --git a/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol-0.4.25.zip b/tests/e2e/detectors/test_data/similar-names/0.4.25/similar_variables.sol-0.4.25.zip deleted file mode 100644 index b91c8f6ffec918553447028a840b0e1095858ddf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1788 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