diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc58ab718..1ae5326a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,7 @@ jobs: type: ["cli", "dapp", "data_dependency", + "path_filtering", # "embark", "erc", # "etherlime", diff --git a/.github/workflows/features.yml b/.github/workflows/features.yml index 7414e9ebe..49db14793 100644 --- a/.github/workflows/features.yml +++ b/.github/workflows/features.yml @@ -45,7 +45,7 @@ jobs: - name: Test with pytest run: | pytest tests/test_features.py - pytest tests/test_constant_folding_unary.py + pytest tests/test_constant_folding.py pytest tests/slithir/test_ternary_expressions.py pytest tests/test_functions_ids.py pytest tests/test_function.py diff --git a/.gitignore b/.gitignore index fe1019a11..2234f5618 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,7 @@ coverage.xml *.cover .hypothesis/ .vscode/ +storage_layout.json # Translations *.mo *.pot diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 798dcc96b..3a30595ec 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -68,8 +68,8 @@ To see the tests coverage, run `pytest tests/test_detectors.py --cov=slither/d ### Parser tests - Create a test in `tests/ast-parsing` -- Run `python ./tests/test_ast_parsing.py --compile`. This will compile the artifact in `tests/compile`. Add the compiled artifact to git. -- Run `python ./tests/test_ast_parsing.py --generate`. This will generate the json artifacts in `tests/expected_json`. Add the generated files to git. +- Run `python ./tests/test_ast_parsing.py --compile`. This will compile the artifact in `tests/ast-parsing/compile`. Add the compiled artifact to git. +- Run `python ./tests/test_ast_parsing.py --generate`. This will generate the json artifacts in `tests/ast-parsing/expected_json`. Add the generated files to git. - Run `pytest ./tests/test_ast_parsing.py` and check that everything worked. To see the tests coverage, run `pytest tests/test_ast_parsing.py --cov=slither/solc_parsing --cov-branch --cov-report html` diff --git a/Dockerfile b/Dockerfile index 2f3251592..71bb9f57f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,14 @@ RUN export DEBIAN_FRONTEND=noninteractive \ && apt-get install -y --no-install-recommends python3-pip \ && rm -rf /var/lib/apt/lists/* +# improve compatibility with amd64 solc in non-amd64 environments (e.g. Docker Desktop on M1 Mac) +ENV QEMU_LD_PREFIX=/usr/x86_64-linux-gnu +RUN if [ ! "$(uname -m)" = "x86_64" ]; then \ + export DEBIAN_FRONTEND=noninteractive \ + && apt-get update \ + && apt-get install -y --no-install-recommends libc6-amd64-cross \ + && rm -rf /var/lib/apt/lists/*; fi + RUN useradd -m slither USER slither diff --git a/README.md b/README.md index 588ae6ee8..8765e0125 100644 --- a/README.md +++ b/README.md @@ -54,83 +54,85 @@ Use [solc-select](https://github.com/crytic/solc-select) if your contracts requi Num | Detector | What it Detects | Impact | Confidence --- | --- | --- | --- | --- 1 | `abiencoderv2-array` | [Storage abiencoderv2 array](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-abiencoderv2-array) | High | High -2 | `array-by-reference` | [Modifying storage array by value](https://github.com/crytic/slither/wiki/Detector-Documentation#modifying-storage-array-by-value) | High | High -3 | `incorrect-shift` | [The order of parameters in a shift instruction is incorrect.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-shift-in-assembly) | High | High -4 | `multiple-constructors` | [Multiple constructor schemes](https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes) | High | High -5 | `name-reused` | [Contract's name reused](https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused) | High | High -6 | `public-mappings-nested` | [Public mappings with nested variables](https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables) | High | High -7 | `rtlo` | [Right-To-Left-Override control character is used](https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character) | High | High -8 | `shadowing-state` | [State variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing) | High | High -9 | `suicidal` | [Functions allowing anyone to destruct the contract](https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal) | High | High -10 | `uninitialized-state` | [Uninitialized state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables) | High | High -11 | `uninitialized-storage` | [Uninitialized storage variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables) | High | High -12 | `unprotected-upgrade` | [Unprotected upgradeable contract](https://github.com/crytic/slither/wiki/Detector-Documentation#unprotected-upgradeable-contract) | High | High -13 | `arbitrary-send` | [Functions that send Ether to arbitrary destinations](https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations) | High | Medium -14 | `controlled-array-length` | [Tainted array length assignment](https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment) | High | Medium -15 | `controlled-delegatecall` | [Controlled delegatecall destination](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) | High | Medium -16 | `delegatecall-loop` | [Payable functions using `delegatecall` inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) | High | Medium -17 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium -18 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium -19 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium -20 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium -21 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium -22 | `enum-conversion` | [Detect dangerous enum conversion](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion) | Medium | High -23 | `erc20-interface` | [Incorrect ERC20 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface) | Medium | High -24 | `erc721-interface` | [Incorrect ERC721 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface) | Medium | High -25 | `incorrect-equality` | [Dangerous strict equalities](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities) | Medium | High -26 | `locked-ether` | [Contracts that lock ether](https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether) | Medium | High -27 | `mapping-deletion` | [Deletion on mapping containing a structure](https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure) | Medium | High -28 | `shadowing-abstract` | [State variables shadowing from abstract contracts](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts) | Medium | High -29 | `tautology` | [Tautology or contradiction](https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction) | Medium | High -30 | `write-after-write` | [Unused write](https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write) | Medium | High -31 | `boolean-cst` | [Misuse of Boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant) | Medium | Medium -32 | `constant-function-asm` | [Constant functions using assembly code](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code) | Medium | Medium -33 | `constant-function-state` | [Constant functions changing the state](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state) | Medium | Medium -34 | `divide-before-multiply` | [Imprecise arithmetic operations order](https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply) | Medium | Medium -35 | `reentrancy-no-eth` | [Reentrancy vulnerabilities (no theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1) | Medium | Medium -36 | `reused-constructor` | [Reused base constructor](https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors) | Medium | Medium -37 | `tx-origin` | [Dangerous usage of `tx.origin`](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin) | Medium | Medium -38 | `unchecked-lowlevel` | [Unchecked low-level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls) | Medium | Medium -39 | `unchecked-send` | [Unchecked send](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send) | Medium | Medium -40 | `uninitialized-local` | [Uninitialized local variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables) | Medium | Medium -41 | `unused-return` | [Unused return values](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return) | Medium | Medium -42 | `incorrect-modifier` | [Modifiers that can return the default value](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier) | Low | High -43 | `shadowing-builtin` | [Built-in symbol shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing) | Low | High -44 | `shadowing-local` | [Local variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing) | Low | High -45 | `uninitialized-fptr-cst` | [Uninitialized function pointer calls in constructors](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors) | Low | High -46 | `variable-scope` | [Local variables used prior their declaration](https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables) | Low | High -47 | `void-cst` | [Constructor called not implemented](https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor) | Low | High -48 | `calls-loop` | [Multiple calls in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop) | Low | Medium -49 | `events-access` | [Missing Events Access Control](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control) | Low | Medium -50 | `events-maths` | [Missing Events Arithmetic](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic) | Low | Medium -51 | `incorrect-unary` | [Dangerous unary expressions](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions) | Low | Medium -52 | `missing-zero-check` | [Missing Zero Address Validation](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation) | Low | Medium -53 | `reentrancy-benign` | [Benign reentrancy vulnerabilities](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) | Low | Medium -54 | `reentrancy-events` | [Reentrancy vulnerabilities leading to out-of-order Events](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) | Low | Medium -55 | `timestamp` | [Dangerous usage of `block.timestamp`](https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp) | Low | Medium -56 | `assembly` | [Assembly usage](https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage) | Informational | High -57 | `assert-state-change` | [Assert state change](https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change) | Informational | High -58 | `boolean-equal` | [Comparison to boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality) | Informational | High -59 | `deprecated-standards` | [Deprecated Solidity Standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) | Informational | High -60 | `erc20-indexed` | [Un-indexed ERC20 event parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) | Informational | High -61 | `function-init-state` | [Function initializing state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) | Informational | High -62 | `low-level-calls` | [Low level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) | Informational | High -63 | `missing-inheritance` | [Missing inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) | Informational | High -64 | `naming-convention` | [Conformity to Solidity naming conventions](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) | Informational | High -65 | `pragma` | [If different pragma directives are used](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) | Informational | High -66 | `redundant-statements` | [Redundant statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) | Informational | High -67 | `solc-version` | [Incorrect Solidity version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) | Informational | High -68 | `unimplemented-functions` | [Unimplemented functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) | Informational | High -69 | `unused-state` | [Unused state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) | Informational | High -70 | `costly-loop` | [Costly operations in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) | Informational | Medium -71 | `dead-code` | [Functions that are not used](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) | Informational | Medium -72 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium -73 | `similar-names` | [Variable names are too similar](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) | Informational | Medium -74 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium -75 | `constable-states` | [State variables that could be declared constant](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant) | Optimization | High -76 | `external-function` | [Public function that could be declared external](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) | Optimization | High -77 | `arbitrary-send-erc20` | [Detect when `msg.sender` is not used as `from` in transferFrom](https://github.com/trailofbits/slither/wiki/Detector-Documentation#arbitrary-send-erc20) -78 | `arbitrary-send-erc20-permit` | [Detect when `msg.sender` is not used as `from` in transferFrom in conjuction with permit](https://github.com/trailofbits/slither/wiki/Detector-Documentation#arbitrary-send-erc20-permit) +2 | `arbitrary-send-erc20` | [transferFrom uses arbitrary `from`](https://github.com/trailofbits/slither/wiki/Detector-Documentation#arbitrary-send-erc20) | High | High +3 | `array-by-reference` | [Modifying storage array by value](https://github.com/crytic/slither/wiki/Detector-Documentation#modifying-storage-array-by-value) | High | High +4 | `incorrect-shift` | [The order of parameters in a shift instruction is incorrect.](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-shift-in-assembly) | High | High +5 | `multiple-constructors` | [Multiple constructor schemes](https://github.com/crytic/slither/wiki/Detector-Documentation#multiple-constructor-schemes) | High | High +6 | `name-reused` | [Contract's name reused](https://github.com/crytic/slither/wiki/Detector-Documentation#name-reused) | High | High +7 | `protected-vars` | [Detected unprotected variables](https://github.com/crytic/slither/wiki/Detector-Documentation#protected-variables) | High | High +8 | `public-mappings-nested` | [Public mappings with nested variables](https://github.com/crytic/slither/wiki/Detector-Documentation#public-mappings-with-nested-variables) | High | High +9 | `rtlo` | [Right-To-Left-Override control character is used](https://github.com/crytic/slither/wiki/Detector-Documentation#right-to-left-override-character) | High | High +10 | `shadowing-state` | [State variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing) | High | High +11 | `suicidal` | [Functions allowing anyone to destruct the contract](https://github.com/crytic/slither/wiki/Detector-Documentation#suicidal) | High | High +12 | `uninitialized-state` | [Uninitialized state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-state-variables) | High | High +13 | `uninitialized-storage` | [Uninitialized storage variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-storage-variables) | High | High +14 | `unprotected-upgrade` | [Unprotected upgradeable contract](https://github.com/crytic/slither/wiki/Detector-Documentation#unprotected-upgradeable-contract) | High | High +15 | `arbitrary-send-erc20-permit` | [transferFrom uses arbitrary from with permit](https://github.com/trailofbits/slither/wiki/Detector-Documentation#arbitrary-send-erc20-permit) | High | Medium +16 | `arbitrary-send-eth` | [Functions that send Ether to arbitrary destinations](https://github.com/crytic/slither/wiki/Detector-Documentation#functions-that-send-ether-to-arbitrary-destinations) | High | Medium +17 | `controlled-array-length` | [Tainted array length assignment](https://github.com/crytic/slither/wiki/Detector-Documentation#array-length-assignment) | High | Medium +18 | `controlled-delegatecall` | [Controlled delegatecall destination](https://github.com/crytic/slither/wiki/Detector-Documentation#controlled-delegatecall) | High | Medium +19 | `delegatecall-loop` | [Payable functions using `delegatecall` inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#payable-functions-using-delegatecall-inside-a-loop) | High | Medium +20 | `msg-value-loop` | [msg.value inside a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#msgvalue-inside-a-loop) | High | Medium +21 | `reentrancy-eth` | [Reentrancy vulnerabilities (theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities) | High | Medium +22 | `storage-array` | [Signed storage integer array compiler bug](https://github.com/crytic/slither/wiki/Detector-Documentation#storage-signed-integer-array) | High | Medium +23 | `unchecked-transfer` | [Unchecked tokens transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer) | High | Medium +24 | `weak-prng` | [Weak PRNG](https://github.com/crytic/slither/wiki/Detector-Documentation#weak-PRNG) | High | Medium +25 | `domain-separator-collision` | [Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()](https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision) | Medium | High +26 | `enum-conversion` | [Detect dangerous enum conversion](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-enum-conversion) | Medium | High +27 | `erc20-interface` | [Incorrect ERC20 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc20-interface) | Medium | High +28 | `erc721-interface` | [Incorrect ERC721 interfaces](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-erc721-interface) | Medium | High +29 | `incorrect-equality` | [Dangerous strict equalities](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-strict-equalities) | Medium | High +30 | `locked-ether` | [Contracts that lock ether](https://github.com/crytic/slither/wiki/Detector-Documentation#contracts-that-lock-ether) | Medium | High +31 | `mapping-deletion` | [Deletion on mapping containing a structure](https://github.com/crytic/slither/wiki/Detector-Documentation#deletion-on-mapping-containing-a-structure) | Medium | High +32 | `shadowing-abstract` | [State variables shadowing from abstract contracts](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variable-shadowing-from-abstract-contracts) | Medium | High +33 | `tautology` | [Tautology or contradiction](https://github.com/crytic/slither/wiki/Detector-Documentation#tautology-or-contradiction) | Medium | High +34 | `write-after-write` | [Unused write](https://github.com/crytic/slither/wiki/Detector-Documentation#write-after-write) | Medium | High +35 | `boolean-cst` | [Misuse of Boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#misuse-of-a-boolean-constant) | Medium | Medium +36 | `constant-function-asm` | [Constant functions using assembly code](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-using-assembly-code) | Medium | Medium +37 | `constant-function-state` | [Constant functions changing the state](https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state) | Medium | Medium +38 | `divide-before-multiply` | [Imprecise arithmetic operations order](https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply) | Medium | Medium +39 | `reentrancy-no-eth` | [Reentrancy vulnerabilities (no theft of ethers)](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-1) | Medium | Medium +40 | `reused-constructor` | [Reused base constructor](https://github.com/crytic/slither/wiki/Detector-Documentation#reused-base-constructors) | Medium | Medium +41 | `tx-origin` | [Dangerous usage of `tx.origin`](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin) | Medium | Medium +42 | `unchecked-lowlevel` | [Unchecked low-level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level-calls) | Medium | Medium +43 | `unchecked-send` | [Unchecked send](https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send) | Medium | Medium +44 | `uninitialized-local` | [Uninitialized local variables](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-local-variables) | Medium | Medium +45 | `unused-return` | [Unused return values](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-return) | Medium | Medium +46 | `incorrect-modifier` | [Modifiers that can return the default value](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-modifier) | Low | High +47 | `shadowing-builtin` | [Built-in symbol shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#builtin-symbol-shadowing) | Low | High +48 | `shadowing-local` | [Local variables shadowing](https://github.com/crytic/slither/wiki/Detector-Documentation#local-variable-shadowing) | Low | High +49 | `uninitialized-fptr-cst` | [Uninitialized function pointer calls in constructors](https://github.com/crytic/slither/wiki/Detector-Documentation#uninitialized-function-pointers-in-constructors) | Low | High +50 | `variable-scope` | [Local variables used prior their declaration](https://github.com/crytic/slither/wiki/Detector-Documentation#pre-declaration-usage-of-local-variables) | Low | High +51 | `void-cst` | [Constructor called not implemented](https://github.com/crytic/slither/wiki/Detector-Documentation#void-constructor) | Low | High +52 | `calls-loop` | [Multiple calls in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation/#calls-inside-a-loop) | Low | Medium +53 | `events-access` | [Missing Events Access Control](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-access-control) | Low | Medium +54 | `events-maths` | [Missing Events Arithmetic](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-events-arithmetic) | Low | Medium +55 | `incorrect-unary` | [Dangerous unary expressions](https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-unary-expressions) | Low | Medium +56 | `missing-zero-check` | [Missing Zero Address Validation](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-zero-address-validation) | Low | Medium +57 | `reentrancy-benign` | [Benign reentrancy vulnerabilities](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-2) | Low | Medium +58 | `reentrancy-events` | [Reentrancy vulnerabilities leading to out-of-order Events](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-3) | Low | Medium +59 | `timestamp` | [Dangerous usage of `block.timestamp`](https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp) | Low | Medium +60 | `assembly` | [Assembly usage](https://github.com/crytic/slither/wiki/Detector-Documentation#assembly-usage) | Informational | High +61 | `assert-state-change` | [Assert state change](https://github.com/crytic/slither/wiki/Detector-Documentation#assert-state-change) | Informational | High +62 | `boolean-equal` | [Comparison to boolean constant](https://github.com/crytic/slither/wiki/Detector-Documentation#boolean-equality) | Informational | High +63 | `deprecated-standards` | [Deprecated Solidity Standards](https://github.com/crytic/slither/wiki/Detector-Documentation#deprecated-standards) | Informational | High +64 | `erc20-indexed` | [Un-indexed ERC20 event parameters](https://github.com/crytic/slither/wiki/Detector-Documentation#unindexed-erc20-event-parameters) | Informational | High +65 | `function-init-state` | [Function initializing state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#function-initializing-state) | Informational | High +66 | `low-level-calls` | [Low level calls](https://github.com/crytic/slither/wiki/Detector-Documentation#low-level-calls) | Informational | High +67 | `missing-inheritance` | [Missing inheritance](https://github.com/crytic/slither/wiki/Detector-Documentation#missing-inheritance) | Informational | High +68 | `naming-convention` | [Conformity to Solidity naming conventions](https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions) | Informational | High +69 | `pragma` | [If different pragma directives are used](https://github.com/crytic/slither/wiki/Detector-Documentation#different-pragma-directives-are-used) | Informational | High +70 | `redundant-statements` | [Redundant statements](https://github.com/crytic/slither/wiki/Detector-Documentation#redundant-statements) | Informational | High +71 | `solc-version` | [Incorrect Solidity version](https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity) | Informational | High +72 | `unimplemented-functions` | [Unimplemented functions](https://github.com/crytic/slither/wiki/Detector-Documentation#unimplemented-functions) | Informational | High +73 | `unused-state` | [Unused state variables](https://github.com/crytic/slither/wiki/Detector-Documentation#unused-state-variable) | Informational | High +74 | `costly-loop` | [Costly operations in a loop](https://github.com/crytic/slither/wiki/Detector-Documentation#costly-operations-inside-a-loop) | Informational | Medium +75 | `dead-code` | [Functions that are not used](https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code) | Informational | Medium +76 | `reentrancy-unlimited-gas` | [Reentrancy vulnerabilities through send and transfer](https://github.com/crytic/slither/wiki/Detector-Documentation#reentrancy-vulnerabilities-4) | Informational | Medium +77 | `similar-names` | [Variable names are too similar](https://github.com/crytic/slither/wiki/Detector-Documentation#variable-names-too-similar) | Informational | Medium +78 | `too-many-digits` | [Conformance to numeric notation best practices](https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits) | Informational | Medium +79 | `constable-states` | [State variables that could be declared constant](https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant) | Optimization | High +80 | `external-function` | [Public function that could be declared external](https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-external) | Optimization | High For more information, see - The [Detector Documentation](https://github.com/crytic/slither/wiki/Detector-Documentation) for details on each detector @@ -249,4 +251,4 @@ Title | Usage | Authors | Venue [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) -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/). \ No newline at end of file +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/). diff --git a/plugin_example/slither_my_plugin/__init__.py b/plugin_example/slither_my_plugin/__init__.py index eabdb147e..9379ac833 100644 --- a/plugin_example/slither_my_plugin/__init__.py +++ b/plugin_example/slither_my_plugin/__init__.py @@ -1,8 +1,13 @@ +from typing import Tuple, List, Type + from slither_my_plugin.detectors.example import Example +from slither.detectors.abstract_detector import AbstractDetector +from slither.printers.abstract_printer import AbstractPrinter + -def make_plugin(): +def make_plugin() -> Tuple[List[Type[AbstractDetector]], List[Type[AbstractPrinter]]]: plugin_detectors = [Example] - plugin_printers = [] + plugin_printers: List[Type[AbstractPrinter]] = [] return plugin_detectors, plugin_printers diff --git a/scripts/ci_test_cli.sh b/scripts/ci_test_cli.sh index 56e6ff0a4..e35bf3ff5 100755 --- a/scripts/ci_test_cli.sh +++ b/scripts/ci_test_cli.sh @@ -4,17 +4,17 @@ solc-select use 0.7.0 -if ! slither "tests/config/test.sol" --solc-ast; then +if ! slither "tests/config/test.sol" --solc-ast --no-fail-pedantic; then echo "--solc-ast failed" exit 1 fi -if ! slither "tests/config/test.sol" --solc-disable-warnings; then +if ! slither "tests/config/test.sol" --solc-disable-warnings --no-fail-pedantic; then echo "--solc-disable-warnings failed" exit 1 fi -if ! slither "tests/config/test.sol" --disable-color; then +if ! slither "tests/config/test.sol" --disable-color --no-fail-pedantic; then echo "--disable-color failed" exit 1 fi diff --git a/scripts/ci_test_path_filtering.sh b/scripts/ci_test_path_filtering.sh new file mode 100644 index 000000000..fb2a18842 --- /dev/null +++ b/scripts/ci_test_path_filtering.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +### Test path filtering across POSIX and Windows + +solc-select use 0.8.0 +slither "tests/test_path_filtering/test_path_filtering.sol" --config "tests/test_path_filtering/slither.config.json" > "output.txt" 2>&1 + +if ! grep -q "0 result(s) found" "output.txt" +then + echo "Path filtering across POSIX and Windows failed" + rm output.txt + exit 5 +else + rm output.txt +fi diff --git a/scripts/ci_test_truffle.sh b/scripts/ci_test_truffle.sh index da1a350c9..0246470f8 100755 --- a/scripts/ci_test_truffle.sh +++ b/scripts/ci_test_truffle.sh @@ -14,9 +14,9 @@ nvm use --lts npm install -g truffle truffle unbox metacoin -if ! slither .; then +if ! slither . --no-fail-pedantic; then echo "Truffle test failed" exit 1 fi -exit 0 \ No newline at end of file +exit 0 diff --git a/setup.py b/setup.py index 4b0c5e8e0..e7ffc8758 100644 --- a/setup.py +++ b/setup.py @@ -8,14 +8,14 @@ setup( description="Slither is a Solidity static analysis framework written in Python 3.", url="https://github.com/crytic/slither", author="Trail of Bits", - version="0.8.3", + version="0.9.0", packages=find_packages(), python_requires=">=3.8", install_requires=[ "prettytable>=0.7.2", - "pysha3>=1.0.2", - # "crytic-compile>=0.2.3", - "crytic-compile", + "pycryptodome>=3.4.6", + "crytic-compile>=0.2.4", + # "crytic-compile@git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile", ], extras_require={ "dev": [ @@ -28,7 +28,6 @@ setup( "solc-select>=v1.0.0b1", ] }, - dependency_links=["git+https://github.com/crytic/crytic-compile.git@master#egg=crytic-compile"], license="AGPL-3.0", long_description=long_description, long_description_content_type="text/markdown", @@ -45,6 +44,7 @@ setup( "slither-prop = slither.tools.properties.__main__:main", "slither-mutate = slither.tools.mutator.__main__:main", "slither-read-storage = slither.tools.read_storage.__main__:main", + "slither-doctor = slither.tools.doctor.__main__:main", ] }, ) diff --git a/slither/__main__.py b/slither/__main__.py index b27c8ae75..70357586e 100644 --- a/slither/__main__.py +++ b/slither/__main__.py @@ -10,11 +10,11 @@ import os import pstats import sys import traceback -from typing import Tuple, Optional, List, Dict +from typing import Tuple, Optional, List, Dict, Type, Union, Any, Sequence from pkg_resources import iter_entry_points, require -from crytic_compile import cryticparser +from crytic_compile import cryticparser, CryticCompile from crytic_compile.platform.standard import generate_standard_export from crytic_compile.platform.etherscan import SUPPORTED_NETWORK from crytic_compile import compile_all, is_supported @@ -55,10 +55,10 @@ logger = logging.getLogger("Slither") def process_single( - target: str, + target: Union[str, CryticCompile], args: argparse.Namespace, - detector_classes: List[AbstractDetector], - printer_classes: List[AbstractPrinter], + detector_classes: List[Type[AbstractDetector]], + printer_classes: List[Type[AbstractPrinter]], ) -> Tuple[Slither, List[Dict], List[Dict], int]: """ The core high-level code for running Slither static analysis. @@ -80,8 +80,8 @@ def process_single( def process_all( target: str, args: argparse.Namespace, - detector_classes: List[AbstractDetector], - printer_classes: List[AbstractPrinter], + detector_classes: List[Type[AbstractDetector]], + printer_classes: List[Type[AbstractPrinter]], ) -> Tuple[List[Slither], List[Dict], List[Dict], int]: compilations = compile_all(target, **vars(args)) slither_instances = [] @@ -109,8 +109,8 @@ def process_all( def _process( slither: Slither, - detector_classes: List[AbstractDetector], - printer_classes: List[AbstractPrinter], + detector_classes: List[Type[AbstractDetector]], + printer_classes: List[Type[AbstractPrinter]], ) -> Tuple[Slither, List[Dict], List[Dict], int]: for detector_cls in detector_classes: slither.register_detector(detector_cls) @@ -137,13 +137,14 @@ def _process( return slither, results_detectors, results_printers, analyzed_contracts_count +# TODO: delete me? def process_from_asts( filenames: List[str], args: argparse.Namespace, - detector_classes: List[AbstractDetector], - printer_classes: List[AbstractPrinter], -): - all_contracts = [] + detector_classes: List[Type[AbstractDetector]], + printer_classes: List[Type[AbstractPrinter]], +) -> Tuple[Slither, List[Dict], List[Dict], int]: + all_contracts: List[str] = [] for filename in filenames: with open(filename, encoding="utf8") as file_open: @@ -162,13 +163,15 @@ def process_from_asts( ################################################################################### -def get_detectors_and_printers(): +def get_detectors_and_printers() -> Tuple[ + List[Type[AbstractDetector]], List[Type[AbstractPrinter]] +]: - detectors = [getattr(all_detectors, name) for name in dir(all_detectors)] - detectors = [d for d in detectors if inspect.isclass(d) and issubclass(d, AbstractDetector)] + detectors_ = [getattr(all_detectors, name) for name in dir(all_detectors)] + detectors = [d for d in detectors_ if inspect.isclass(d) and issubclass(d, AbstractDetector)] - printers = [getattr(all_printers, name) for name in dir(all_printers)] - printers = [p for p in printers if inspect.isclass(p) and issubclass(p, AbstractPrinter)] + printers_ = [getattr(all_printers, name) for name in dir(all_printers)] + printers = [p for p in printers_ if inspect.isclass(p) and issubclass(p, AbstractPrinter)] # Handle plugins! for entry_point in iter_entry_points(group="slither_analyzer.plugin", name=None): @@ -194,8 +197,8 @@ def get_detectors_and_printers(): # pylint: disable=too-many-branches def choose_detectors( - args: argparse.Namespace, all_detector_classes: List[AbstractDetector] -) -> List[AbstractDetector]: + args: argparse.Namespace, all_detector_classes: List[Type[AbstractDetector]] +) -> List[Type[AbstractDetector]]: # If detectors are specified, run only these ones detectors_to_run = [] @@ -245,8 +248,8 @@ def choose_detectors( def choose_printers( - args: argparse.Namespace, all_printer_classes: List[AbstractPrinter] -) -> List[AbstractPrinter]: + args: argparse.Namespace, all_printer_classes: List[Type[AbstractPrinter]] +) -> List[Type[AbstractPrinter]]: printers_to_run = [] # disable default printer @@ -273,19 +276,22 @@ def choose_printers( ################################################################################### -def parse_filter_paths(args): +def parse_filter_paths(args: argparse.Namespace) -> List[str]: if args.filter_paths: return args.filter_paths.split(",") return [] -def parse_args(detector_classes, printer_classes): # pylint: disable=too-many-statements +# pylint: disable=too-many-statements +def parse_args( + detector_classes: List[Type[AbstractDetector]], printer_classes: List[Type[AbstractPrinter]] +) -> argparse.Namespace: usage = "slither target [flag]\n" usage += "\ntarget can be:\n" usage += "\t- file.sol // a Solidity file\n" usage += "\t- project_directory // a project directory. See https://github.com/crytic/crytic-compile/#crytic-compile for the supported platforms\n" - usage += "\t- 0x.. // a contract on mainet\n" + usage += "\t- 0x.. // a contract on mainnet\n" usage += f"\t- NETWORK:0x.. // a contract on a different network. Supported networks: {','.join(x[:-1] for x in SUPPORTED_NETWORK)}\n" parser = argparse.ArgumentParser( @@ -397,11 +403,19 @@ def parse_args(detector_classes, printer_classes): # pylint: disable=too-many-s group_detector.add_argument( "--fail-pedantic", - help="Fail if any finding is detected", + help="Return the number of findings in the exit code", action="store_true", default=defaults_flag_in_config["fail_pedantic"], ) + group_detector.add_argument( + "--no-fail-pedantic", + help="Do not return the number of findings in the exit code. Opposite of --fail-pedantic", + dest="fail_pedantic", + action="store_false", + required=False, + ) + group_detector.add_argument( "--fail-low", help="Fail if low or greater impact finding is detected", @@ -614,7 +628,9 @@ class ListDetectors(argparse.Action): # pylint: disable=too-few-public-methods class ListDetectorsJson(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, *args, **kwargs): # pylint: disable=signature-differs + def __call__( + self, parser: Any, *args: Any, **kwargs: Any + ) -> None: # pylint: disable=signature-differs detectors, _ = get_detectors_and_printers() detector_types_json = output_detectors_json(detectors) print(json.dumps(detector_types_json)) @@ -622,22 +638,38 @@ class ListDetectorsJson(argparse.Action): # pylint: disable=too-few-public-meth class ListPrinters(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, *args, **kwargs): # pylint: disable=signature-differs + def __call__( + self, parser: Any, *args: Any, **kwargs: Any + ) -> None: # pylint: disable=signature-differs _, printers = get_detectors_and_printers() output_printers(printers) parser.exit() class OutputMarkdown(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, args, values, option_string=None): + def __call__( + self, + parser: Any, + args: Any, + values: Optional[Union[str, Sequence[Any]]], + option_string: Any = None, + ) -> None: detectors, printers = get_detectors_and_printers() + assert isinstance(values, str) output_to_markdown(detectors, printers, values) parser.exit() class OutputWiki(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, args, values, option_string=None): + def __call__( + self, + parser: Any, + args: Any, + values: Optional[Union[str, Sequence[Any]]], + option_string: Any = None, + ) -> None: detectors, _ = get_detectors_and_printers() + assert isinstance(values, str) output_wiki(detectors, values) parser.exit() @@ -670,7 +702,7 @@ class FormatterCryticCompile(logging.Formatter): ################################################################################### -def main(): +def main() -> None: # Codebase with complex domninators can lead to a lot of SSA recursive call sys.setrecursionlimit(1500) @@ -681,8 +713,9 @@ def main(): # pylint: disable=too-many-statements,too-many-branches,too-many-locals def main_impl( - all_detector_classes: List[AbstractDetector], all_printer_classes: List[AbstractPrinter] -): + all_detector_classes: List[Type[AbstractDetector]], + all_printer_classes: List[Type[AbstractPrinter]], +) -> None: """ :param all_detector_classes: A list of all detectors that can be included/excluded. :param all_printer_classes: A list of all printers that can be included. @@ -748,8 +781,8 @@ def main_impl( crytic_compile_error.propagate = False crytic_compile_error.setLevel(logging.INFO) - results_detectors = [] - results_printers = [] + results_detectors: List[Dict] = [] + results_printers: List[Dict] = [] try: filename = args.filename @@ -798,6 +831,7 @@ def main_impl( if "compilations" in args.json_types: compilation_results = [] for slither_instance in slither_instances: + assert slither_instance.crytic_compile compilation_results.append( generate_standard_export(slither_instance.crytic_compile) ) @@ -848,7 +882,7 @@ def main_impl( except Exception: # pylint: disable=broad-except output_error = traceback.format_exc() - logging.error(traceback.print_exc()) + traceback.print_exc() logging.error(f"Error in {args.filename}") # pylint: disable=logging-fstring-interpolation logging.error(output_error) @@ -871,7 +905,7 @@ def main_impl( if outputting_zip: output_to_zip(args.zip, output_error, json_results, args.zip_type) - if args.perf: + if args.perf and cp: cp.disable() stats = pstats.Stats(cp).sort_stats("cumtime") stats.print_stats() diff --git a/slither/core/declarations/contract.py b/slither/core/declarations/contract.py index 2e02dbf51..eb2ac9a2e 100644 --- a/slither/core/declarations/contract.py +++ b/slither/core/declarations/contract.py @@ -322,6 +322,13 @@ class Contract(SourceMapping): # pylint: disable=too-many-public-methods """ return list(self._variables.values()) + @property + def state_variables_entry_points(self) -> List["StateVariable"]: + """ + list(StateVariable): List of the state variables that are public. + """ + return [var for var in self._variables.values() if var.visibility == "public"] + @property def state_variables_ordered(self) -> List["StateVariable"]: """ diff --git a/slither/core/declarations/function.py b/slither/core/declarations/function.py index 96b4573e9..face2d364 100644 --- a/slither/core/declarations/function.py +++ b/slither/core/declarations/function.py @@ -960,6 +960,11 @@ class Function(SourceMapping, metaclass=ABCMeta): # pylint: disable=too-many-pu """ Return a signature following the Solidity Standard Contract and converted into address + + It might still keep internal types (ex: structure name) for internal functions. + The reason is that internal functions allows recursive structure definition, which + can't be converted following the Solidity stand ard + :return: the solidity signature """ if self._solidity_signature is None: diff --git a/slither/core/declarations/structure.py b/slither/core/declarations/structure.py index 39b1948ee..8f6d8c50a 100644 --- a/slither/core/declarations/structure.py +++ b/slither/core/declarations/structure.py @@ -8,10 +8,10 @@ if TYPE_CHECKING: class Structure(SourceMapping): - def __init__(self, compilation_unit: "SlitherCompilationUnit"): + def __init__(self, compilation_unit: "SlitherCompilationUnit") -> None: super().__init__() self._name: Optional[str] = None - self._canonical_name = None + self._canonical_name: Optional[str] = None self._elems: Dict[str, "StructureVariable"] = {} # Name of the elements in the order of declaration self._elems_ordered: List[str] = [] @@ -19,25 +19,27 @@ class Structure(SourceMapping): @property def canonical_name(self) -> str: + assert self._canonical_name return self._canonical_name @canonical_name.setter - def canonical_name(self, name: str): + def canonical_name(self, name: str) -> None: self._canonical_name = name @property def name(self) -> str: + assert self._name return self._name @name.setter - def name(self, new_name: str): + def name(self, new_name: str) -> None: self._name = new_name @property def elems(self) -> Dict[str, "StructureVariable"]: return self._elems - def add_elem_in_order(self, s: str): + def add_elem_in_order(self, s: str) -> None: self._elems_ordered.append(s) @property @@ -47,5 +49,5 @@ class Structure(SourceMapping): ret.append(self._elems[e]) return ret - def __str__(self): + def __str__(self) -> str: return self.name diff --git a/slither/core/expressions/literal.py b/slither/core/expressions/literal.py index 3303a9aa8..87090b93f 100644 --- a/slither/core/expressions/literal.py +++ b/slither/core/expressions/literal.py @@ -1,7 +1,9 @@ from typing import Optional, Union, TYPE_CHECKING from slither.core.expressions.expression import Expression +from slither.core.solidity_types.elementary_type import Fixed, Int, Ufixed, Uint from slither.utils.arithmetic import convert_subdenomination +from slither.utils.integer_conversion import convert_string_to_int if TYPE_CHECKING: from slither.core.solidity_types.type import Type @@ -29,6 +31,10 @@ class Literal(Expression): def __str__(self): if self.subdenomination: return str(convert_subdenomination(self._value, self.subdenomination)) + + if self.type in Int + Uint + Fixed + Ufixed + ["address"]: + return str(convert_string_to_int(self._value)) + # be sure to handle any character return str(self._value) diff --git a/slither/core/expressions/tuple_expression.py b/slither/core/expressions/tuple_expression.py index 7f14601f4..1fd8fc795 100644 --- a/slither/core/expressions/tuple_expression.py +++ b/slither/core/expressions/tuple_expression.py @@ -4,7 +4,7 @@ from slither.core.expressions.expression import Expression class TupleExpression(Expression): - def __init__(self, expressions): + def __init__(self, expressions: List[Expression]) -> None: assert all(isinstance(x, Expression) for x in expressions if x) super().__init__() self._expressions = expressions @@ -13,6 +13,6 @@ class TupleExpression(Expression): def expressions(self) -> List[Expression]: return self._expressions - def __str__(self): + def __str__(self) -> str: expressions_str = [str(e) for e in self.expressions] return "(" + ",".join(expressions_str) + ")" diff --git a/slither/core/solidity_types/array_type.py b/slither/core/solidity_types/array_type.py index 97d735c89..59a15dcc6 100644 --- a/slither/core/solidity_types/array_type.py +++ b/slither/core/solidity_types/array_type.py @@ -53,7 +53,7 @@ class ArrayType(Type): def storage_size(self) -> Tuple[int, bool]: if self._length_value: elem_size, _ = self._type.storage_size - return elem_size * int(self._length_value.value), True + return elem_size * int(str(self._length_value)), True return 32, True def __str__(self): diff --git a/slither/core/source_mapping/source_mapping.py b/slither/core/source_mapping/source_mapping.py index 7ceabd568..ee5211c7c 100644 --- a/slither/core/source_mapping/source_mapping.py +++ b/slither/core/source_mapping/source_mapping.py @@ -162,13 +162,15 @@ def _convert_source_mapping( class SourceMapping(Context, metaclass=ABCMeta): - def __init__(self): + def __init__(self) -> None: super().__init__() # self._source_mapping: Optional[Dict] = None self.source_mapping: Source = Source() self.references: List[Source] = [] - def set_offset(self, offset: Union["Source", str], compilation_unit: "SlitherCompilationUnit"): + def set_offset( + self, offset: Union["Source", str], compilation_unit: "SlitherCompilationUnit" + ) -> None: if isinstance(offset, Source): self.source_mapping.start = offset.start self.source_mapping.length = offset.length @@ -184,6 +186,6 @@ class SourceMapping(Context, metaclass=ABCMeta): def add_reference_from_raw_source( self, offset: str, compilation_unit: "SlitherCompilationUnit" - ): + ) -> None: s = _convert_source_mapping(offset, compilation_unit) self.references.append(s) diff --git a/slither/detectors/abstract_detector.py b/slither/detectors/abstract_detector.py index 528981c92..4ebead96a 100644 --- a/slither/detectors/abstract_detector.py +++ b/slither/detectors/abstract_detector.py @@ -189,7 +189,7 @@ class AbstractDetector(metaclass=abc.ABCMeta): if results and self.slither.triage_mode: while True: indexes = input( - f'Results to hide during next runs: "0,1,...,{len(results)}" or "All" (enter to not hide results): ' + f'Results to hide during next runs: "0,1,...,{len(results)}" or "All" (enter to not hide results):\n' ) if indexes == "All": self.slither.save_results_to_hide(results) diff --git a/slither/detectors/all_detectors.py b/slither/detectors/all_detectors.py index a79dcaf51..2c8d24428 100644 --- a/slither/detectors/all_detectors.py +++ b/slither/detectors/all_detectors.py @@ -84,3 +84,4 @@ from .statements.write_after_write import WriteAfterWrite from .statements.msg_value_in_loop import MsgValueInLoop from .statements.delegatecall_in_loop import DelegatecallInLoop from .functions.protected_variable import ProtectedVariables +from .functions.permit_domain_signature_collision import DomainSeparatorCollision diff --git a/slither/detectors/attributes/incorrect_solc.py b/slither/detectors/attributes/incorrect_solc.py index 5292c19e3..d6838328e 100644 --- a/slither/detectors/attributes/incorrect_solc.py +++ b/slither/detectors/attributes/incorrect_solc.py @@ -43,7 +43,14 @@ Deploy with any of the following Solidity versions: - 0.5.16 - 0.5.17 - 0.6.11 - 0.6.12 - 0.7.5 - 0.7.6 -- 0.8.4 - 0.8.7 +- 0.8.16 + +The recommendations take into account: +- Risks related to recent releases +- Risks of complex code generation changes +- Risks of new language features +- Risks of known bugs + Use a simple pragma version that allows any of these versions. Consider using the latest version of Solidity for testing.""" # endregion wiki_recommendation @@ -52,24 +59,13 @@ Consider using the latest version of Solidity for testing.""" OLD_VERSION_TXT = "allows old versions" LESS_THAN_TXT = "uses lesser than" - TOO_RECENT_VERSION_TXT = "necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.7" + TOO_RECENT_VERSION_TXT = "necessitates a version too recent to be trusted. Consider deploying with 0.6.12/0.7.6/0.8.16" BUGGY_VERSION_TXT = ( "is known to contain severe issues (https://solidity.readthedocs.io/en/latest/bugs.html)" ) # Indicates the allowed versions. Must be formatted in increasing order. - ALLOWED_VERSIONS = [ - "0.5.16", - "0.5.17", - "0.6.11", - "0.6.12", - "0.7.5", - "0.7.6", - "0.8.4", - "0.8.5", - "0.8.6", - "0.8.7", - ] + ALLOWED_VERSIONS = ["0.5.16", "0.5.17", "0.6.11", "0.6.12", "0.7.5", "0.7.6", "0.8.16"] # Indicates the versions that should not be used. BUGGY_VERSIONS = [ diff --git a/slither/detectors/erc/erc20/arbitrary_send_erc20_no_permit.py b/slither/detectors/erc/erc20/arbitrary_send_erc20_no_permit.py index 8e29ecbef..f43b6302e 100644 --- a/slither/detectors/erc/erc20/arbitrary_send_erc20_no_permit.py +++ b/slither/detectors/erc/erc20/arbitrary_send_erc20_no_permit.py @@ -14,7 +14,7 @@ class ArbitrarySendErc20NoPermit(AbstractDetector): IMPACT = DetectorClassification.HIGH CONFIDENCE = DetectorClassification.HIGH - WIKI = "https://github.com/trailofbits/slither/wiki/Detector-Documentation#arbitrary-send-erc20" + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom" WIKI_TITLE = "Arbitrary `from` in transferFrom" WIKI_DESCRIPTION = "Detect when `msg.sender` is not used as `from` in transferFrom." diff --git a/slither/detectors/erc/erc20/arbitrary_send_erc20_permit.py b/slither/detectors/erc/erc20/arbitrary_send_erc20_permit.py index 48e80772b..1d311c442 100644 --- a/slither/detectors/erc/erc20/arbitrary_send_erc20_permit.py +++ b/slither/detectors/erc/erc20/arbitrary_send_erc20_permit.py @@ -14,7 +14,7 @@ class ArbitrarySendErc20Permit(AbstractDetector): IMPACT = DetectorClassification.HIGH CONFIDENCE = DetectorClassification.MEDIUM - WIKI = "https://github.com/trailofbits/slither/wiki/Detector-Documentation#arbitrary-send-erc20-permit" + WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom-used-with-permit" WIKI_TITLE = "Arbitrary `from` in transferFrom used with permit" WIKI_DESCRIPTION = ( diff --git a/slither/detectors/functions/permit_domain_signature_collision.py b/slither/detectors/functions/permit_domain_signature_collision.py new file mode 100644 index 000000000..7142d7cf1 --- /dev/null +++ b/slither/detectors/functions/permit_domain_signature_collision.py @@ -0,0 +1,72 @@ +""" +Module detecting EIP-2612 domain separator collision +""" +from typing import Union, List + +from slither.core.declarations import Function +from slither.core.solidity_types.elementary_type import ElementaryType +from slither.core.variables.state_variable import StateVariable +from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from slither.utils.function import get_function_id + + +class DomainSeparatorCollision(AbstractDetector): + """ + Domain separator collision + """ + + ARGUMENT = "domain-separator-collision" + HELP = "Detects ERC20 tokens that have a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR()" + IMPACT = DetectorClassification.MEDIUM + CONFIDENCE = DetectorClassification.HIGH + + WIKI = ( + "https://github.com/crytic/slither/wiki/Detector-Documentation#domain-separator-collision" + ) + + WIKI_TITLE = "Domain separator collision" + WIKI_DESCRIPTION = "An ERC20 token has a function whose signature collides with EIP-2612's DOMAIN_SEPARATOR(), causing unanticipated behavior for contracts using `permit` functionality." + + # region wiki_exploit_scenario + WIKI_EXPLOIT_SCENARIO = """ +```solidity +contract Contract{ + function some_collisions() external() {} +} +``` +`some_collision` clashes with EIP-2612's DOMAIN_SEPARATOR() and will interfere with contract's using `permit`.""" + # endregion wiki_exploit_scenario + + WIKI_RECOMMENDATION = "Remove or rename the function that collides with DOMAIN_SEPARATOR()." + + def _detect(self): + domain_sig = get_function_id("DOMAIN_SEPARATOR()") + for contract in self.compilation_unit.contracts_derived: + if contract.is_erc20(): + funcs_and_vars: List[Union[Function, StateVariable]] = contract.functions_entry_points + contract.state_variables_entry_points # type: ignore + for func_or_var in funcs_and_vars: + # External/ public function names should not collide with DOMAIN_SEPARATOR() + hash_collision = ( + func_or_var.solidity_signature != "DOMAIN_SEPARATOR()" + and get_function_id(func_or_var.solidity_signature) == domain_sig + ) + # DOMAIN_SEPARATOR() should return bytes32 + incorrect_return_type = func_or_var.solidity_signature == "DOMAIN_SEPARATOR()" + if incorrect_return_type: + if isinstance(func_or_var, Function): + incorrect_return_type = ( + not func_or_var.return_type + or func_or_var.return_type[0] != ElementaryType("bytes32") + ) + else: + assert isinstance(func_or_var, StateVariable) + incorrect_return_type = func_or_var.type != ElementaryType("bytes32") + if hash_collision or incorrect_return_type: + info = [ + "The function signature of ", + func_or_var, + " collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + ] + res = self.generate_result(info) + return [res] + return [] diff --git a/slither/detectors/statements/divide_before_multiply.py b/slither/detectors/statements/divide_before_multiply.py index 5a5132fdd..7691c3a17 100644 --- a/slither/detectors/statements/divide_before_multiply.py +++ b/slither/detectors/statements/divide_before_multiply.py @@ -189,7 +189,7 @@ In general, it's usually a good idea to re-arrange arithmetic to perform multipl nodes.sort(key=lambda x: x.node_id) for node in nodes: - info += ["\t-", node, "\n"] + info += ["\t- ", node, "\n"] res = self.generate_result(info) results.append(res) diff --git a/slither/detectors/statements/unprotected_upgradeable.py b/slither/detectors/statements/unprotected_upgradeable.py index c91b5bb16..25be6a5ae 100644 --- a/slither/detectors/statements/unprotected_upgradeable.py +++ b/slither/detectors/statements/unprotected_upgradeable.py @@ -65,21 +65,22 @@ class UnprotectedUpgradeable(AbstractDetector): # region wiki_exploit_scenario WIKI_EXPLOIT_SCENARIO = """ - ```solidity - contract Buggy is Initializable{ - address payable owner; - - function initialize() external initializer{ - require(owner == address(0)); - owner = msg.sender; - } - function kill() external{ - require(msg.sender == owner); - selfdestruct(owner); - } +```solidity +contract Buggy is Initializable{ + address payable owner; + + function initialize() external initializer{ + require(owner == address(0)); + owner = msg.sender; + } + function kill() external{ + require(msg.sender == owner); + selfdestruct(owner); } - ``` - Buggy is an upgradeable contract. Anyone can call initialize on the logic contract, and destruct the contract.""" +} +``` +Buggy is an upgradeable contract. Anyone can call initialize on the logic contract, and destruct the contract. +""" # endregion wiki_exploit_scenario WIKI_RECOMMENDATION = ( diff --git a/slither/detectors/variables/possible_const_state_variables.py b/slither/detectors/variables/possible_const_state_variables.py index 47af9741b..e5b35bb79 100644 --- a/slither/detectors/variables/possible_const_state_variables.py +++ b/slither/detectors/variables/possible_const_state_variables.py @@ -1,15 +1,40 @@ """ Module detecting state variables that could be declared as constant """ +from typing import Set, List, Dict + from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.solidity_types.elementary_type import ElementaryType +from slither.core.solidity_types.user_defined_type import UserDefinedType +from slither.core.variables.variable import Variable from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification +from slither.utils.output import Output from slither.visitors.expression.export_values import ExportValues +from slither.core.declarations import Contract, Function from slither.core.declarations.solidity_variables import SolidityFunction from slither.core.variables.state_variable import StateVariable from slither.formatters.variables.possible_const_state_variables import custom_format +def _is_valid_type(v: StateVariable) -> bool: + t = v.type + if isinstance(t, ElementaryType): + return True + if isinstance(t, UserDefinedType) and isinstance(t.type, Contract): + return True + return False + + +def _valid_candidate(v: StateVariable) -> bool: + return _is_valid_type(v) and not (v.is_constant or v.is_immutable) + + +def _is_constant_var(v: Variable) -> bool: + if isinstance(v, StateVariable): + return v.is_constant + return False + + class ConstCandidateStateVars(AbstractDetector): """ State variables that could be declared as constant detector. @@ -29,10 +54,6 @@ class ConstCandidateStateVars(AbstractDetector): WIKI_DESCRIPTION = "Constant state variables should be declared constant to save gas." WIKI_RECOMMENDATION = "Add the `constant` attributes to state variables that never change." - @staticmethod - def _valid_candidate(v): - return isinstance(v.type, ElementaryType) and not (v.is_constant or v.is_immutable) - # https://solidity.readthedocs.io/en/v0.5.2/contracts.html#constant-state-variables valid_solidity_function = [ SolidityFunction("keccak256()"), @@ -46,13 +67,7 @@ class ConstCandidateStateVars(AbstractDetector): SolidityFunction("mulmod(uint256,uint256,uint256)"), ] - @staticmethod - def _is_constant_var(v): - if isinstance(v, StateVariable): - return v.is_constant - return False - - def _constant_initial_expression(self, v): + def _constant_initial_expression(self, v: Variable) -> bool: if not v.expression: return True @@ -60,34 +75,39 @@ class ConstCandidateStateVars(AbstractDetector): values = export.result() if not values: return True - if all( - (val in self.valid_solidity_function or self._is_constant_var(val) for val in values) - ): + if all((val in self.valid_solidity_function or _is_constant_var(val) for val in values)): return True return False - def _detect(self): + def _detect(self) -> List[Output]: """Detect state variables that could be const""" results = [] - all_variables = [c.state_variables for c in self.compilation_unit.contracts] - all_variables = {item for sublist in all_variables for item in sublist} - all_non_constant_elementary_variables = { - v for v in all_variables if self._valid_candidate(v) + all_variables_l = [c.state_variables for c in self.compilation_unit.contracts] + all_variables: Set[StateVariable] = { + item for sublist in all_variables_l for item in sublist } - - all_functions = [c.all_functions_called for c in self.compilation_unit.contracts] - all_functions = list({item for sublist in all_functions for item in sublist}) + all_non_constant_elementary_variables = {v for v in all_variables if _valid_candidate(v)} + + all_functions_nested = [c.all_functions_called for c in self.compilation_unit.contracts] + all_functions = list( + { + item1 + for sublist in all_functions_nested + for item1 in sublist + if isinstance(item1, Function) + } + ) all_variables_written = [ f.state_variables_written for f in all_functions if not f.is_constructor_variables ] all_variables_written = {item for sublist in all_variables_written for item in sublist} - constable_variables = [ + constable_variables: List[Variable] = [ v for v in all_non_constant_elementary_variables - if (not v in all_variables_written) and self._constant_initial_expression(v) + if (v not in all_variables_written) and self._constant_initial_expression(v) ] # Order for deterministic results constable_variables = sorted(constable_variables, key=lambda x: x.canonical_name) @@ -101,5 +121,5 @@ class ConstCandidateStateVars(AbstractDetector): return results @staticmethod - def _format(compilation_unit: SlitherCompilationUnit, result): + def _format(compilation_unit: SlitherCompilationUnit, result: Dict) -> None: custom_format(compilation_unit, result) diff --git a/slither/printers/summary/function_ids.py b/slither/printers/summary/function_ids.py index 368a81382..ca02dd754 100644 --- a/slither/printers/summary/function_ids.py +++ b/slither/printers/summary/function_ids.py @@ -9,7 +9,7 @@ from slither.utils.myprettytable import MyPrettyTable class FunctionIds(AbstractPrinter): ARGUMENT = "function-id" - HELP = "Print the keccack256 signature of the functions" + HELP = "Print the keccak256 signature of the functions" WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#function-id" diff --git a/slither/slither.py b/slither/slither.py index 59bbf8a5f..dcfc0ad7e 100644 --- a/slither/slither.py +++ b/slither/slither.py @@ -1,5 +1,5 @@ import logging -from typing import Union, List, ValuesView +from typing import Union, List, ValuesView, Type, Dict from crytic_compile import CryticCompile, InvalidCompilation @@ -19,7 +19,9 @@ logger_detector = logging.getLogger("Detectors") logger_printer = logging.getLogger("Printers") -def _check_common_things(thing_name, cls, base_cls, instances_list): +def _check_common_things( + thing_name: str, cls: Type, base_cls: Type, instances_list: List[Type[AbstractDetector]] +) -> None: if not issubclass(cls, base_cls) or cls is base_cls: raise Exception( @@ -178,7 +180,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes def detectors_optimization(self): return [d for d in self.detectors if d.IMPACT == DetectorClassification.OPTIMIZATION] - def register_detector(self, detector_class): + def register_detector(self, detector_class: Type[AbstractDetector]) -> None: """ :param detector_class: Class inheriting from `AbstractDetector`. """ @@ -188,7 +190,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes instance = detector_class(compilation_unit, self, logger_detector) self._detectors.append(instance) - def register_printer(self, printer_class): + def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: """ :param printer_class: Class inheriting from `AbstractPrinter`. """ @@ -197,7 +199,7 @@ class Slither(SlitherCore): # pylint: disable=too-many-instance-attributes instance = printer_class(self, logger_printer) self._printers.append(instance) - def run_detectors(self): + def run_detectors(self) -> List[Dict]: """ :return: List of registered detectors results. """ diff --git a/slither/slithir/convert.py b/slither/slithir/convert.py index 829a23e92..a35c50220 100644 --- a/slither/slithir/convert.py +++ b/slither/slithir/convert.py @@ -827,7 +827,7 @@ def extract_tmp_call(ins: TmpCall, contract: Optional[Contract]): # pylint: dis # lib L { event E()} # ... # emit L.E(); - if str(ins.ori.variable_right) in ins.ori.variable_left.events_as_dict: + if str(ins.ori.variable_right) in [f.name for f in ins.ori.variable_left.events]: eventcall = EventCall(ins.ori.variable_right) eventcall.set_expression(ins.expression) eventcall.call_id = ins.call_id diff --git a/slither/slithir/operations/call.py b/slither/slithir/operations/call.py index 2e0c3d1df..07304fa99 100644 --- a/slither/slithir/operations/call.py +++ b/slither/slithir/operations/call.py @@ -1,8 +1,10 @@ +from typing import Optional, List + from slither.slithir.operations.operation import Operation class Call(Operation): - def __init__(self): + def __init__(self) -> None: super().__init__() self._arguments = [] @@ -14,7 +16,7 @@ class Call(Operation): def arguments(self, v): self._arguments = v - def can_reenter(self, _callstack=None) -> bool: # pylint: disable=no-self-use + def can_reenter(self, _callstack: Optional[List] = None) -> bool: # pylint: disable=no-self-use """ Must be called after slithIR analysis pass :return: bool diff --git a/slither/slithir/operations/event_call.py b/slither/slithir/operations/event_call.py index a04013140..6ef846d4b 100644 --- a/slither/slithir/operations/event_call.py +++ b/slither/slithir/operations/event_call.py @@ -17,4 +17,4 @@ class EventCall(Call): def __str__(self): args = [str(a) for a in self.arguments] - return f"Emit {self.name}({'.'.join(args)})" + return f"Emit {self.name}({','.join(args)})" diff --git a/slither/slithir/tmp_operations/tmp_call.py b/slither/slithir/tmp_operations/tmp_call.py index e9562b1c1..fb6641139 100644 --- a/slither/slithir/tmp_operations/tmp_call.py +++ b/slither/slithir/tmp_operations/tmp_call.py @@ -63,14 +63,14 @@ class TmpCall(OperationWithLValue): # pylint: disable=too-many-instance-attribu def call_id(self): return self._callid - @property - def read(self): - return [self.called] - @call_id.setter def call_id(self, c): self._callid = c + @property + def read(self): + return [self.called] + @property def called(self): return self._called diff --git a/slither/slithir/tmp_operations/tmp_new_elementary_type.py b/slither/slithir/tmp_operations/tmp_new_elementary_type.py index 357c063a7..d7a4f5e1b 100644 --- a/slither/slithir/tmp_operations/tmp_new_elementary_type.py +++ b/slither/slithir/tmp_operations/tmp_new_elementary_type.py @@ -1,21 +1,23 @@ +from typing import List + from slither.slithir.operations.lvalue import OperationWithLValue from slither.core.solidity_types.elementary_type import ElementaryType class TmpNewElementaryType(OperationWithLValue): - def __init__(self, new_type, lvalue): + def __init__(self, new_type: ElementaryType, lvalue): assert isinstance(new_type, ElementaryType) super().__init__() - self._type = new_type + self._type: ElementaryType = new_type self._lvalue = lvalue @property - def read(self): + def read(self) -> List: return [] @property - def type(self): + def type(self) -> ElementaryType: return self._type - def __str__(self): + def __str__(self) -> str: return f"{self.lvalue} = new {self._type}" diff --git a/slither/slithir/variables/constant.py b/slither/slithir/variables/constant.py index 09a5ee34f..5da2d9cc0 100644 --- a/slither/slithir/variables/constant.py +++ b/slither/slithir/variables/constant.py @@ -1,4 +1,3 @@ -from decimal import Decimal from functools import total_ordering from slither.core.solidity_types.elementary_type import ElementaryType, Int, Uint @@ -33,7 +32,7 @@ class Constant(SlithIRVariable): else: if val.isdigit(): self._type = ElementaryType("uint256") - self._val = int(Decimal(val)) + self._val = convert_string_to_int(val) else: self._type = ElementaryType("string") self._val = val diff --git a/slither/solc_parsing/declarations/modifier.py b/slither/solc_parsing/declarations/modifier.py index 3fdc22d4e..a3f07da7f 100644 --- a/slither/solc_parsing/declarations/modifier.py +++ b/slither/solc_parsing/declarations/modifier.py @@ -62,7 +62,7 @@ class ModifierSolc(FunctionSolc): self._content_was_analyzed = True if self.is_compact_ast: - body = self._functionNotParsed["body"] + body = self._functionNotParsed.get("body", None) if body and body[self.get_key()] == "Block": self._function.is_implemented = True diff --git a/slither/solc_parsing/slither_compilation_unit_solc.py b/slither/solc_parsing/slither_compilation_unit_solc.py index 3054b4470..d12bda1b4 100644 --- a/slither/solc_parsing/slither_compilation_unit_solc.py +++ b/slither/solc_parsing/slither_compilation_unit_solc.py @@ -257,7 +257,6 @@ class SlitherCompilationUnitSolc: scope.accessible_scopes.append(get_imported_scope) elif top_level_data[self.get_key()] == "StructDefinition": - scope = self.compilation_unit.get_scope(filename) st = StructureTopLevel(self.compilation_unit, scope) st.set_offset(top_level_data["src"], self._compilation_unit) st_parser = StructureTopLevelSolc(st, top_level_data, self) @@ -279,7 +278,6 @@ class SlitherCompilationUnitSolc: self._variables_top_level_parser.append(var_parser) scope.variables[var.name] = var elif top_level_data[self.get_key()] == "FunctionDefinition": - scope = self.compilation_unit.get_scope(filename) func = FunctionTopLevel(self._compilation_unit, scope) scope.functions.add(func) func.set_offset(top_level_data["src"], self._compilation_unit) @@ -290,7 +288,6 @@ class SlitherCompilationUnitSolc: self.add_function_or_modifier_parser(func_parser) elif top_level_data[self.get_key()] == "ErrorDefinition": - scope = self.compilation_unit.get_scope(filename) custom_error = CustomErrorTopLevel(self._compilation_unit, scope) custom_error.set_offset(top_level_data["src"], self._compilation_unit) diff --git a/slither/solc_parsing/yul/parse_yul.py b/slither/solc_parsing/yul/parse_yul.py index 05974ae65..8c9ee427e 100644 --- a/slither/solc_parsing/yul/parse_yul.py +++ b/slither/solc_parsing/yul/parse_yul.py @@ -675,7 +675,7 @@ def parse_yul_variable_declaration( the assignment """ - if not ast["value"]: + if "value" not in ast or not ast["value"]: return None return _parse_yul_assignment_common(root, node, ast, "variables") @@ -807,7 +807,16 @@ def parse_yul_identifier(root: YulScope, _node: YulNode, ast: Dict) -> Optional[ def parse_yul_literal(_root: YulScope, _node: YulNode, ast: Dict) -> Optional[Expression]: kind = ast["kind"] - value = ast["value"] + + if kind == "string": + # Solc 0.8.0 use value, 0.8.16 use hexValue - not sure when this changed was made + if "value" in ast: + value = ast["value"] + else: + value = ast["hexValue"] + else: + # number/bool + value = ast["value"] if not kind: kind = "bool" if value in ["true", "false"] else "uint256" diff --git a/slither/tools/demo/__main__.py b/slither/tools/demo/__main__.py index 37d265bb1..5bc2c7c8e 100644 --- a/slither/tools/demo/__main__.py +++ b/slither/tools/demo/__main__.py @@ -9,7 +9,7 @@ logging.getLogger("Slither").setLevel(logging.INFO) logger = logging.getLogger("Slither-demo") -def parse_args(): +def parse_args() -> argparse.Namespace: """ Parse the underlying arguments for the program. :return: Returns the arguments for the program. @@ -26,7 +26,7 @@ def parse_args(): return parser.parse_args() -def main(): +def main() -> None: args = parse_args() # Perform slither analysis on the given filename diff --git a/slither/tools/doctor/README.md b/slither/tools/doctor/README.md new file mode 100644 index 000000000..ce724f109 --- /dev/null +++ b/slither/tools/doctor/README.md @@ -0,0 +1,3 @@ +# Slither doctor + +Slither doctor is a tool designed to troubleshoot running Slither on a project. \ No newline at end of file diff --git a/slither/tools/doctor/__init__.py b/slither/tools/doctor/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/slither/tools/doctor/__main__.py b/slither/tools/doctor/__main__.py new file mode 100644 index 000000000..94ae865ec --- /dev/null +++ b/slither/tools/doctor/__main__.py @@ -0,0 +1,37 @@ +import argparse + +from crytic_compile import cryticparser + +from slither.tools.doctor.utils import report_section +from slither.tools.doctor.checks import ALL_CHECKS + + +def parse_args() -> argparse.Namespace: + """ + Parse the underlying arguments for the program. + :return: Returns the arguments for the program. + """ + parser = argparse.ArgumentParser( + description="Troubleshoot running Slither on your project", + usage="slither-doctor project", + ) + + parser.add_argument("project", help="The codebase to be tested.") + + # Add default arguments from crytic-compile + cryticparser.init(parser) + + return parser.parse_args() + + +def main(): + args = parse_args() + kwargs = vars(args) + + for check in ALL_CHECKS: + with report_section(check.title): + check.function(**kwargs) + + +if __name__ == "__main__": + main() diff --git a/slither/tools/doctor/checks/__init__.py b/slither/tools/doctor/checks/__init__.py new file mode 100644 index 000000000..762c60b5d --- /dev/null +++ b/slither/tools/doctor/checks/__init__.py @@ -0,0 +1,18 @@ +from typing import Callable, List +from dataclasses import dataclass + +from slither.tools.doctor.checks.platform import compile_project, detect_platform +from slither.tools.doctor.checks.versions import show_versions + + +@dataclass +class Check: + title: str + function: Callable[..., None] + + +ALL_CHECKS: List[Check] = [ + Check("Software versions", show_versions), + Check("Project platform", detect_platform), + Check("Project compilation", compile_project), +] diff --git a/slither/tools/doctor/checks/platform.py b/slither/tools/doctor/checks/platform.py new file mode 100644 index 000000000..91d0d16eb --- /dev/null +++ b/slither/tools/doctor/checks/platform.py @@ -0,0 +1,59 @@ +import logging +from pathlib import Path + +from crytic_compile import crytic_compile + +from slither.tools.doctor.utils import snip_section +from slither.utils.colors import red, yellow, green + + +def detect_platform(project: str, **kwargs) -> None: + path = Path(project) + if path.is_file(): + print( + yellow( + f"{project!r} is a file. Using it as target will manually compile your code with solc and _not_ use a compilation framework. Is that what you meant to do?" + ) + ) + return + + print(f"Trying to detect project type for {project!r}") + + supported_platforms = crytic_compile.get_platforms() + skip_platforms = {"solc", "solc-json", "archive", "standard", "etherscan"} + detected_platforms = { + platform.NAME: platform.is_supported(project, **kwargs) + for platform in supported_platforms + if platform.NAME.lower() not in skip_platforms + } + platform_qty = len([platform for platform, state in detected_platforms.items() if state]) + + print("Is this project using...") + for platform, state in detected_platforms.items(): + print(f" => {platform + '?':<15}{state and green('Yes') or red('No')}") + print() + + if platform_qty == 0: + print(red("No platform was detected! This doesn't sound right.")) + print( + yellow( + "Are you trying to analyze a folder with standalone solidity files, without using a compilation framework? If that's the case, then this is okay." + ) + ) + elif platform_qty > 1: + print(red("More than one platform was detected! This doesn't sound right.")) + print( + red("Please use `--compile-force-framework` in Slither to force the correct framework.") + ) + else: + print(green("A single platform was detected."), yellow("Is it the one you expected?")) + + +def compile_project(project: str, **kwargs): + print("Invoking crytic-compile on the project, please wait...") + + try: + crytic_compile.CryticCompile(project, **kwargs) + except Exception as e: # pylint: disable=broad-except + with snip_section("Project compilation failed :( The following error was generated:"): + logging.exception(e) diff --git a/slither/tools/doctor/checks/versions.py b/slither/tools/doctor/checks/versions.py new file mode 100644 index 000000000..909bccf55 --- /dev/null +++ b/slither/tools/doctor/checks/versions.py @@ -0,0 +1,59 @@ +from importlib import metadata +import json +from typing import Optional +import urllib + +from packaging.version import parse, LegacyVersion, Version + +from slither.utils.colors import yellow, green + + +def get_installed_version(name: str) -> Optional[LegacyVersion | Version]: + try: + return parse(metadata.version(name)) + except metadata.PackageNotFoundError: + return None + + +def get_github_version(name: str) -> Optional[LegacyVersion | Version]: + try: + with urllib.request.urlopen( + f"https://api.github.com/repos/crytic/{name}/releases/latest" + ) as response: + text = response.read() + data = json.loads(text) + return parse(data["tag_name"]) + except: # pylint: disable=bare-except + return None + + +def show_versions(**_kwargs) -> None: + versions = { + "Slither": (get_installed_version("slither-analyzer"), get_github_version("slither")), + "crytic-compile": ( + get_installed_version("crytic-compile"), + get_github_version("crytic-compile"), + ), + "solc-select": (get_installed_version("solc-select"), get_github_version("solc-select")), + } + + outdated = { + name + for name, (installed, latest) in versions.items() + if not installed or not latest or latest > installed + } + + for name, (installed, latest) in versions.items(): + color = yellow if name in outdated else green + print(f"{name + ':':<16}{color(installed or 'N/A'):<16} (latest is {latest or 'Unknown'})") + + if len(outdated) > 0: + print() + print( + yellow( + f"Please update {', '.join(outdated)} to the latest release before creating a bug report." + ) + ) + else: + print() + print(green("Your tools are up to date.")) diff --git a/slither/tools/doctor/utils.py b/slither/tools/doctor/utils.py new file mode 100644 index 000000000..bc6112cc8 --- /dev/null +++ b/slither/tools/doctor/utils.py @@ -0,0 +1,28 @@ +from contextlib import contextmanager +import logging +from typing import Optional +from slither.utils.colors import bold, yellow, red + + +@contextmanager +def snip_section(message: Optional[str]) -> None: + if message: + print(red(message), end="\n\n") + + print(yellow("---- snip 8< ----")) + yield + print(yellow("---- >8 snip ----")) + + +@contextmanager +def report_section(title: str) -> None: + print(bold(f"## {title}"), end="\n\n") + try: + yield + except Exception as e: # pylint: disable=broad-except + with snip_section( + "slither-doctor failed unexpectedly! Please report this on the Slither GitHub issue tracker, and include the output below:" + ): + logging.exception(e) + finally: + print(end="\n\n") diff --git a/slither/tools/erc_conformance/__main__.py b/slither/tools/erc_conformance/__main__.py index 45e57b55c..ef594a7c6 100644 --- a/slither/tools/erc_conformance/__main__.py +++ b/slither/tools/erc_conformance/__main__.py @@ -1,6 +1,7 @@ import argparse import logging from collections import defaultdict +from typing import Any, Dict, List from crytic_compile import cryticparser from slither import Slither @@ -26,7 +27,7 @@ logger.propagate = False ADDITIONAL_CHECKS = {"ERC20": check_erc20, "ERC1155": check_erc1155} -def parse_args(): +def parse_args() -> argparse.Namespace: """ Parse the underlying arguments for the program. :return: Returns the arguments for the program. @@ -63,20 +64,20 @@ def parse_args(): return parser.parse_args() -def _log_error(err, args): +def _log_error(err: Any, args: argparse.Namespace) -> None: if args.json: output_to_json(args.json, str(err), {"upgradeability-check": []}) logger.error(err) -def main(): +def main() -> None: args = parse_args() # Perform slither analysis on the given filename slither = Slither(args.project, **vars(args)) - ret = defaultdict(list) + ret: Dict[str, List] = defaultdict(list) if args.erc.upper() in ERCS: diff --git a/slither/tools/erc_conformance/erc/ercs.py b/slither/tools/erc_conformance/erc/ercs.py index ef459eef9..a6b9050ae 100644 --- a/slither/tools/erc_conformance/erc/ercs.py +++ b/slither/tools/erc_conformance/erc/ercs.py @@ -1,7 +1,10 @@ import logging +from typing import Dict, List, Optional, Set +from slither.core.declarations import Contract from slither.slithir.operations import EventCall from slither.utils import output +from slither.utils.erc import ERC, ERC_EVENT from slither.utils.type import ( export_nested_types_from_variable, export_return_type_from_variable, @@ -11,7 +14,7 @@ logger = logging.getLogger("Slither-conformance") # pylint: disable=too-many-locals,too-many-branches,too-many-statements -def _check_signature(erc_function, contract, ret): +def _check_signature(erc_function: ERC, contract: Contract, ret: Dict) -> None: name = erc_function.name parameters = erc_function.parameters return_type = erc_function.return_type @@ -146,7 +149,7 @@ def _check_signature(erc_function, contract, ret): ret["missing_event_emmited"].append(missing_event_emmited.data) -def _check_events(erc_event, contract, ret): +def _check_events(erc_event: ERC_EVENT, contract: Contract, ret: Dict[str, List]) -> None: name = erc_event.name parameters = erc_event.parameters indexes = erc_event.indexes @@ -180,7 +183,13 @@ def _check_events(erc_event, contract, ret): ret["missing_event_index"].append(missing_event_index.data) -def generic_erc_checks(contract, erc_functions, erc_events, ret, explored=None): +def generic_erc_checks( + contract: Contract, + erc_functions: List[ERC], + erc_events: List[ERC_EVENT], + ret: Dict[str, List], + explored: Optional[Set[Contract]] = None, +) -> None: if explored is None: explored = set() diff --git a/slither/tools/flattening/__main__.py b/slither/tools/flattening/__main__.py index 977b84896..bf9856fe8 100644 --- a/slither/tools/flattening/__main__.py +++ b/slither/tools/flattening/__main__.py @@ -18,7 +18,7 @@ logger = logging.getLogger("Slither") logger.setLevel(logging.INFO) -def parse_args(): +def parse_args() -> argparse.Namespace: """ Parse the underlying arguments for the program. :return: Returns the arguments for the program. @@ -106,7 +106,7 @@ def parse_args(): return parser.parse_args() -def main(): +def main() -> None: args = parse_args() slither = Slither(args.filename, **vars(args)) diff --git a/slither/tools/flattening/flattening.py b/slither/tools/flattening/flattening.py index ef793f2f2..74a93ba2d 100644 --- a/slither/tools/flattening/flattening.py +++ b/slither/tools/flattening/flattening.py @@ -4,7 +4,7 @@ import uuid from collections import namedtuple from enum import Enum as PythonEnum from pathlib import Path -from typing import List, Set, Dict, Optional +from typing import List, Set, Dict, Optional, Sequence from slither.core.compilation_unit import SlitherCompilationUnit from slither.core.declarations import SolidityFunction, EnumContract, StructureContract @@ -78,12 +78,12 @@ class Flattening: self._get_source_code_top_level(compilation_unit.variables_top_level) self._get_source_code_top_level(compilation_unit.functions_top_level) - def _get_source_code_top_level(self, elems: List[TopLevel]) -> None: + def _get_source_code_top_level(self, elems: Sequence[TopLevel]) -> None: for elem in elems: src_mapping = elem.source_mapping - content = self._compilation_unit.core.source_code[src_mapping["filename_absolute"]] - start = src_mapping["start"] - end = src_mapping["start"] + src_mapping["length"] + content = self._compilation_unit.core.source_code[src_mapping.filename.absolute] + start = src_mapping.start + end = src_mapping.start + src_mapping.length self._source_codes_top_level[elem] = content[start:end] def _check_abi_encoder_v2(self): diff --git a/slither/tools/kspec_coverage/__main__.py b/slither/tools/kspec_coverage/__main__.py index b6ce0f81b..19933e0fe 100644 --- a/slither/tools/kspec_coverage/__main__.py +++ b/slither/tools/kspec_coverage/__main__.py @@ -16,7 +16,7 @@ logger.handlers[0].setFormatter(formatter) logger.propagate = False -def parse_args(): +def parse_args() -> argparse.Namespace: """ Parse the underlying arguments for the program. :return: Returns the arguments for the program. @@ -56,7 +56,7 @@ def parse_args(): return parser.parse_args() -def main(): +def main() -> None: # ------------------------------ # Usage: slither-kspec-coverage contract kspec # Example: slither-kspec-coverage contract.sol kspec.md diff --git a/slither/tools/kspec_coverage/kspec_coverage.py b/slither/tools/kspec_coverage/kspec_coverage.py index 569a35cf1..f8c2d8cf2 100755 --- a/slither/tools/kspec_coverage/kspec_coverage.py +++ b/slither/tools/kspec_coverage/kspec_coverage.py @@ -1,8 +1,10 @@ +import argparse + from slither.tools.kspec_coverage.analysis import run_analysis from slither import Slither -def kspec_coverage(args): +def kspec_coverage(args: argparse.Namespace) -> None: contract = args.contract kspec = args.kspec diff --git a/slither/tools/mutator/__main__.py b/slither/tools/mutator/__main__.py index 442b4849d..78b86d681 100644 --- a/slither/tools/mutator/__main__.py +++ b/slither/tools/mutator/__main__.py @@ -2,6 +2,7 @@ import argparse import inspect import logging import sys +from typing import Type, List, Any from crytic_compile import cryticparser @@ -22,7 +23,7 @@ logger.setLevel(logging.INFO) ################################################################################### -def parse_args(): +def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Experimental smart contract mutator. Based on https://arxiv.org/abs/2006.11597", usage="slither-mutate target", @@ -48,14 +49,16 @@ def parse_args(): return parser.parse_args() -def _get_mutators(): - detectors = [getattr(all_mutators, name) for name in dir(all_mutators)] - detectors = [c for c in detectors if inspect.isclass(c) and issubclass(c, AbstractMutator)] +def _get_mutators() -> List[Type[AbstractMutator]]: + detectors_ = [getattr(all_mutators, name) for name in dir(all_mutators)] + detectors = [c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractMutator)] return detectors class ListMutators(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, *args, **kwargs): # pylint: disable=signature-differs + def __call__( + self, parser: Any, *args: Any, **kwargs: Any + ) -> None: # pylint: disable=signature-differs checks = _get_mutators() output_mutators(checks) parser.exit() diff --git a/slither/tools/possible_paths/__main__.py b/slither/tools/possible_paths/__main__.py index 29cd05c46..b993d266a 100644 --- a/slither/tools/possible_paths/__main__.py +++ b/slither/tools/possible_paths/__main__.py @@ -5,6 +5,7 @@ from argparse import ArgumentParser, Namespace from crytic_compile import cryticparser from slither import Slither +from slither.core.declarations import FunctionContract from slither.utils.colors import red from slither.tools.possible_paths.possible_paths import ( find_target_paths, @@ -58,7 +59,11 @@ def main() -> None: # Print out all target functions. print("Target functions:") for target in targets: - print(f"- {target.contract_declarer.name}.{target.full_name}") + if isinstance(target, FunctionContract): + print(f"- {target.contract_declarer.name}.{target.full_name}") + else: + pass + # TODO implement me print("\n") # Obtain all paths which reach the target functions. diff --git a/slither/tools/possible_paths/possible_paths.py b/slither/tools/possible_paths/possible_paths.py index 9e52ed6b7..6e836e76a 100644 --- a/slither/tools/possible_paths/possible_paths.py +++ b/slither/tools/possible_paths/possible_paths.py @@ -1,8 +1,15 @@ +from typing import List, Tuple, Union, Optional, Set + +from slither import Slither +from slither.core.declarations import Function, FunctionContract +from slither.core.slither_core import SlitherCore + + class ResolveFunctionException(Exception): pass -def resolve_function(slither, contract_name, function_name): +def resolve_function(slither: SlitherCore, contract_name: str, function_name: str) -> Function: """ Resolves a function instance, given a contract name and function. :param contract_name: The name of the contract the function is declared in. @@ -32,7 +39,9 @@ def resolve_function(slither, contract_name, function_name): return target_function -def resolve_functions(slither, functions): +def resolve_functions( + slither: Slither, functions: List[Union[str, Tuple[str, str]]] +) -> List[Function]: """ Resolves the provided function descriptors. :param functions: A list of tuples (contract_name, function_name) or str (of form "ContractName.FunctionName") @@ -40,7 +49,7 @@ def resolve_functions(slither, functions): :return: Returns a list of resolved functions. """ # Create the resolved list. - resolved = [] + resolved: List[Function] = [] # Verify that the provided argument is a list. if not isinstance(functions, list): @@ -72,24 +81,31 @@ def resolve_functions(slither, functions): return resolved -def all_function_definitions(function): +def all_function_definitions(function: Function) -> List[Function]: """ Obtains a list of representing this function and any base definitions :param function: The function to obtain all definitions at and beneath. :return: Returns a list composed of the provided function definition and any base definitions. """ - return [function] + [ + # TODO implement me + if not isinstance(function, FunctionContract): + return [] + ret: List[Function] = [function] + ret += [ f for c in function.contract.inheritance for f in c.functions_and_modifiers_declared if f.full_name == function.full_name ] + return ret -def __find_target_paths(slither, target_function, current_path=None): +def __find_target_paths( + slither: SlitherCore, target_function: Function, current_path: Optional[List[Function]] = None +) -> Set[Tuple[Function, ...]]: current_path = current_path if current_path else [] # Create our results list - results = set() + results: Set[Tuple[Function, ...]] = set() # Add our current function to the path. current_path = [target_function] + current_path @@ -106,9 +122,12 @@ def __find_target_paths(slither, target_function, current_path=None): continue # Find all function calls in this function (except for low level) - called_functions = [f for (_, f) in function.high_level_calls + function.library_calls] - called_functions += function.internal_calls - called_functions = set(called_functions) + called_functions_list = [ + f for (_, f) in function.high_level_calls if isinstance(f, Function) + ] + called_functions_list += [f for (_, f) in function.library_calls] + called_functions_list += [f for f in function.internal_calls if isinstance(f, Function)] + called_functions = set(called_functions_list) # If any of our target functions are reachable from this function, it's a result. if all_target_functions.intersection(called_functions): @@ -123,14 +142,16 @@ def __find_target_paths(slither, target_function, current_path=None): return results -def find_target_paths(slither, target_functions): +def find_target_paths( + slither: SlitherCore, target_functions: List[Function] +) -> Set[Tuple[Function, ...]]: """ Obtains all functions which can lead to any of the target functions being called. :param target_functions: The functions we are interested in reaching. :return: Returns a list of all functions which can reach any of the target_functions. """ # Create our results list - results = set() + results: Set[Tuple[Function, ...]] = set() # Loop for each target function for target_function in target_functions: diff --git a/slither/tools/properties/__main__.py b/slither/tools/properties/__main__.py index 91c990669..10837bb4b 100644 --- a/slither/tools/properties/__main__.py +++ b/slither/tools/properties/__main__.py @@ -1,6 +1,7 @@ import argparse import logging import sys +from typing import Any from crytic_compile import cryticparser @@ -26,7 +27,7 @@ logger.handlers[0].setFormatter(formatter) logger.propagate = False -def _all_scenarios(): +def _all_scenarios() -> str: txt = "\n" txt += "#################### ERC20 ####################\n" for k, value in ERC20_PROPERTIES.items(): @@ -35,29 +36,33 @@ def _all_scenarios(): return txt -def _all_properties(): +def _all_properties() -> MyPrettyTable: table = MyPrettyTable(["Num", "Description", "Scenario"]) idx = 0 for scenario, value in ERC20_PROPERTIES.items(): for prop in value.properties: - table.add_row([idx, prop.description, scenario]) + table.add_row([str(idx), prop.description, scenario]) idx = idx + 1 return table class ListScenarios(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, *args, **kwargs): # pylint: disable=signature-differs + def __call__( + self, parser: Any, *args: Any, **kwargs: Any + ) -> None: # pylint: disable=signature-differs logger.info(_all_scenarios()) parser.exit() class ListProperties(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, *args, **kwargs): # pylint: disable=signature-differs + def __call__( + self, parser: Any, *args: Any, **kwargs: Any + ) -> None: # pylint: disable=signature-differs logger.info(_all_properties()) parser.exit() -def parse_args(): +def parse_args() -> argparse.Namespace: """ Parse the underlying arguments for the program. :return: Returns the arguments for the program. @@ -120,7 +125,7 @@ def parse_args(): return parser.parse_args() -def main(): +def main() -> None: args = parse_args() # Perform slither analysis on the given filename diff --git a/slither/tools/properties/platforms/truffle.py b/slither/tools/properties/platforms/truffle.py index dc83eb273..7d2f3d9b6 100644 --- a/slither/tools/properties/platforms/truffle.py +++ b/slither/tools/properties/platforms/truffle.py @@ -15,7 +15,7 @@ PATTERN_TRUFFLE_MIGRATION = re.compile("^[0-9]*_") logger = logging.getLogger("Slither") -def _extract_caller(p: PropertyCaller): +def _extract_caller(p: PropertyCaller) -> List[str]: if p == PropertyCaller.OWNER: return ["owner"] if p == PropertyCaller.SENDER: @@ -28,7 +28,7 @@ def _extract_caller(p: PropertyCaller): return ["user"] -def _helpers(): +def _helpers() -> str: """ Generate two functions: - catchRevertThrowReturnFalse: check if the call revert/throw or return false @@ -75,7 +75,7 @@ def generate_unit_test( # pylint: disable=too-many-arguments,too-many-branches output_dir: Path, addresses: Addresses, assert_message: str = "", -): +) -> Path: """ Generate unit tests files :param test_contract: @@ -134,7 +134,7 @@ def generate_unit_test( # pylint: disable=too-many-arguments,too-many-branches return output_dir -def generate_migration(test_contract: str, output_dir: Path, owner_address: str): +def generate_migration(test_contract: str, output_dir: Path, owner_address: str) -> None: """ Generate migration file :param test_contract: diff --git a/slither/tools/properties/utils.py b/slither/tools/properties/utils.py index bdc5bdd68..5a0153211 100644 --- a/slither/tools/properties/utils.py +++ b/slither/tools/properties/utils.py @@ -12,7 +12,7 @@ def write_file( content: str, allow_overwrite: bool = True, discard_if_exist: bool = False, -): +) -> None: """ Write the content into output_dir/filename :param output_dir: diff --git a/slither/tools/read_storage/README.md b/slither/tools/read_storage/README.md index 91491a364..677b2c772 100644 --- a/slither/tools/read_storage/README.md +++ b/slither/tools/read_storage/README.md @@ -18,9 +18,10 @@ optional arguments: --struct-var STRUCT_VAR The name of the variable whose value will be returned from a struct. --storage-address STORAGE_ADDRESS The address of the storage contract (if a proxy pattern is used). --contract-name CONTRACT_NAME The name of the logic contract. - --layout Toggle used to write a JSON file with the entire storage layout. + --json FILE Write the entire storage layout in JSON format to the specified FILE --value Toggle used to include values in output. --max-depth MAX_DEPTH Max depth to search in data structure. + --block BLOCK_NUMBER Block number to retrieve storage from (requires archive rpc node) ``` ### Examples @@ -28,19 +29,19 @@ optional arguments: Retrieve the storage slots of a local contract: ```shell -slither-read-storage file.sol 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --layout +slither-read-storage file.sol 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --json storage_layout.json ``` Retrieve the storage slots of a contract verified on an Etherscan-like platform: ```shell -slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --layout +slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --json storage_layout.json ``` To retrieve the values as well, pass `--value` and `--rpc-url $RPC_URL`: ```shell -slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --layout --rpc-url $RPC_URL --value +slither-read-storage 0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8 --json storage_layout.json --rpc-url $RPC_URL --value ``` To view only the slot of the `slot0` structure variable, pass `--variable-name slot0`: @@ -79,7 +80,7 @@ slither-read-storage 0xa2327a938Febf5FEC13baCFb16Ae10EcBc4cbDCF --variable-name Take Avalanche, for instance: ```shell - slither-read-storage avax:0x0000000000000000000000000000000000000000 --layout --value --rpc-url $AVAX_RPC_URL + slither-read-storage avax:0x0000000000000000000000000000000000000000 --json storage_layout.json --value --rpc-url $AVAX_RPC_URL ``` ## Limitations diff --git a/slither/tools/read_storage/__main__.py b/slither/tools/read_storage/__main__.py index f3cc90efc..1a8901321 100644 --- a/slither/tools/read_storage/__main__.py +++ b/slither/tools/read_storage/__main__.py @@ -21,9 +21,9 @@ def parse_args() -> argparse.Namespace: "\nTo retrieve a single variable's value:\n" + "\tslither-read-storage $TARGET address --variable-name $NAME\n" + "To retrieve a contract's storage layout:\n" - + "\tslither-read-storage $TARGET address --contract-name $NAME --layout\n" + + "\tslither-read-storage $TARGET address --contract-name $NAME --json storage_layout.json\n" + "To retrieve a contract's storage layout and values:\n" - + "\tslither-read-storage $TARGET address --contract-name $NAME --layout --value\n" + + "\tslither-read-storage $TARGET address --contract-name $NAME --json storage_layout.json --value\n" + "TARGET can be a contract address or project directory" ), ) @@ -98,6 +98,12 @@ def parse_args() -> argparse.Namespace: parser.add_argument("--max-depth", help="Max depth to search in data structure.", default=20) + parser.add_argument( + "--block", + help="The block number to read storage from. Requires an archive node to be provided as the RPC url.", + default="latest", + ) + cryticparser.init(parser) return parser.parse_args() @@ -122,6 +128,11 @@ def main() -> None: srs = SlitherReadStorage(contracts, args.max_depth) + try: + srs.block = int(args.block) + except ValueError: + srs.block = str(args.block or "latest") + if args.rpc_url: # Remove target prefix e.g. rinkeby:0x0 -> 0x0. address = target[target.find(":") + 1 :] diff --git a/slither/tools/read_storage/read_storage.py b/slither/tools/read_storage/read_storage.py index c9523f733..bb662c4d5 100644 --- a/slither/tools/read_storage/read_storage.py +++ b/slither/tools/read_storage/read_storage.py @@ -53,15 +53,16 @@ class SlitherReadStorageException(Exception): # pylint: disable=too-many-instance-attributes class SlitherReadStorage: def __init__(self, contracts: List[Contract], max_depth: int) -> None: + self._checksum_address: Optional[ChecksumAddress] = None self._contracts: List[Contract] = contracts - self._max_depth: int = max_depth self._log: str = "" + self._max_depth: int = max_depth self._slot_info: Dict[str, SlotInfo] = {} self._target_variables: List[Tuple[Contract, StateVariable]] = [] self._web3: Optional[Web3] = None - self._checksum_address: Optional[ChecksumAddress] = None - self.storage_address: Optional[str] = None + self.block: Union[str, int] = "latest" self.rpc: Optional[str] = None + self.storage_address: Optional[str] = None self.table: Optional[MyPrettyTable] = None @property @@ -231,7 +232,10 @@ class SlitherReadStorage: :param slot_info: """ hex_bytes = get_storage_data( - self.web3, self.checksum_address, int.to_bytes(slot_info.slot, 32, byteorder="big") + self.web3, + self.checksum_address, + int.to_bytes(slot_info.slot, 32, byteorder="big"), + self.block, ) slot_info.value = self.convert_value_to_type( hex_bytes, slot_info.size, slot_info.offset, slot_info.type_string @@ -249,7 +253,7 @@ class SlitherReadStorage: func, [ (contract, var) - for var in contract.variables + for var in contract.state_variables_ordered if not var.is_constant and not var.is_immutable ], ) @@ -609,7 +613,10 @@ class SlitherReadStorage: # Convert from hexadecimal to decimal. val = int( get_storage_data( - self.web3, self.checksum_address, int.to_bytes(slot, 32, byteorder="big") + self.web3, + self.checksum_address, + int.to_bytes(slot, 32, byteorder="big"), + self.block, ).hex(), 16, ) diff --git a/slither/tools/read_storage/utils/utils.py b/slither/tools/read_storage/utils/utils.py index db2052286..3e51e2181 100644 --- a/slither/tools/read_storage/utils/utils.py +++ b/slither/tools/read_storage/utils/utils.py @@ -55,16 +55,19 @@ def coerce_type( return value.hex() -def get_storage_data(web3, checksum_address: ChecksumAddress, slot: bytes) -> bytes: +def get_storage_data( + web3, checksum_address: ChecksumAddress, slot: bytes, block: Union[int, str] +) -> bytes: """ Retrieves the storage data from the blockchain at target address and slot. Args: web3: Web3 instance provider. checksum_address (ChecksumAddress): The address to query. slot (bytes): The slot to retrieve data from. + block (optional int|str): The block number to retrieve data from Returns: (HexBytes): The slot's storage data. """ - return bytes(web3.eth.get_storage_at(checksum_address, slot)).rjust( + return bytes(web3.eth.get_storage_at(checksum_address, slot, block)).rjust( 32, bytes(1) ) # pad to 32 bytes diff --git a/slither/tools/similarity/__main__.py b/slither/tools/similarity/__main__.py index 21ba88681..86673fccd 100755 --- a/slither/tools/similarity/__main__.py +++ b/slither/tools/similarity/__main__.py @@ -17,7 +17,7 @@ logger = logging.getLogger("Slither-simil") modes = ["info", "test", "train", "plot"] -def parse_args(): +def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Code similarity detection tool. For usage, see https://github.com/crytic/slither/wiki/Code-Similarity-detector" ) @@ -78,7 +78,7 @@ def parse_args(): ################################################################################### -def main(): +def main() -> None: args = parse_args() default_log = logging.INFO diff --git a/slither/tools/similarity/encode.py b/slither/tools/similarity/encode.py index c69de91b8..9889644fb 100644 --- a/slither/tools/similarity/encode.py +++ b/slither/tools/similarity/encode.py @@ -74,7 +74,7 @@ def parse_target(target): return None -def load_and_encode(infile, vmodel, ext=None, nsamples=None, **kwargs): +def load_and_encode(infile: str, vmodel, ext=None, nsamples=None, **kwargs): r = {} if infile.endswith(".npz"): r = load_cache(infile, nsamples=nsamples) diff --git a/slither/tools/similarity/info.py b/slither/tools/similarity/info.py index 95aadea6a..c9f9753d1 100644 --- a/slither/tools/similarity/info.py +++ b/slither/tools/similarity/info.py @@ -1,3 +1,4 @@ +import argparse import logging import sys import os.path @@ -10,7 +11,7 @@ logging.basicConfig() logger = logging.getLogger("Slither-simil") -def info(args): +def info(args: argparse.Namespace) -> None: try: diff --git a/slither/tools/similarity/plot.py b/slither/tools/similarity/plot.py index bbdeec2cf..f11e92129 100644 --- a/slither/tools/similarity/plot.py +++ b/slither/tools/similarity/plot.py @@ -1,3 +1,4 @@ +import argparse import logging import random import sys @@ -23,7 +24,7 @@ except ImportError: logger = logging.getLogger("Slither-simil") -def plot(args): # pylint: disable=too-many-locals +def plot(args: argparse.Namespace) -> None: # pylint: disable=too-many-locals if decomposition is None or plt is None: logger.error( diff --git a/slither/tools/similarity/train.py b/slither/tools/similarity/train.py index a0d06c944..ccadf4926 100755 --- a/slither/tools/similarity/train.py +++ b/slither/tools/similarity/train.py @@ -1,3 +1,4 @@ +import argparse import logging import os import sys @@ -10,7 +11,7 @@ from slither.tools.similarity.model import train_unsupervised logger = logging.getLogger("Slither-simil") -def train(args): # pylint: disable=too-many-locals +def train(args: argparse.Namespace) -> None: # pylint: disable=too-many-locals try: last_data_train_filename = "last_data_train.txt" diff --git a/slither/tools/slither_format/__main__.py b/slither/tools/slither_format/__main__.py index a3d63d922..85c0a3917 100644 --- a/slither/tools/slither_format/__main__.py +++ b/slither/tools/slither_format/__main__.py @@ -23,7 +23,7 @@ available_detectors = [ ] -def parse_args(): +def parse_args() -> argparse.Namespace: """ Parse the underlying arguments for the program. :return: Returns the arguments for the program. @@ -90,7 +90,7 @@ def parse_args(): return parser.parse_args() -def main(): +def main() -> None: # ------------------------------ # Usage: python3 -m slither_format filename # Example: python3 -m slither_format contract.sol diff --git a/slither/tools/slither_format/slither_format.py b/slither/tools/slither_format/slither_format.py index 794307100..c165b3fbb 100644 --- a/slither/tools/slither_format/slither_format.py +++ b/slither/tools/slither_format/slither_format.py @@ -1,5 +1,9 @@ import logging from pathlib import Path +from typing import Type, List, Dict + +from slither import Slither +from slither.detectors.abstract_detector import AbstractDetector from slither.detectors.variables.unused_state_variables import UnusedStateVars from slither.detectors.attributes.incorrect_solc import IncorrectSolc from slither.detectors.attributes.constant_pragma import ConstantPragma @@ -13,7 +17,7 @@ from slither.utils.colors import yellow logging.basicConfig(level=logging.INFO) logger = logging.getLogger("Slither.Format") -all_detectors = { +all_detectors: Dict[str, Type[AbstractDetector]] = { "unused-state": UnusedStateVars, "solc-version": IncorrectSolc, "pragma": ConstantPragma, @@ -25,7 +29,7 @@ all_detectors = { } -def slither_format(slither, **kwargs): # pylint: disable=too-many-locals +def slither_format(slither: Slither, **kwargs: Dict) -> None: # pylint: disable=too-many-locals """' Keyword Args: detectors_to_run (str): Comma-separated list of detectors, defaults to all @@ -85,9 +89,11 @@ def slither_format(slither, **kwargs): # pylint: disable=too-many-locals ################################################################################### -def choose_detectors(detectors_to_run, detectors_to_exclude): +def choose_detectors( + detectors_to_run: str, detectors_to_exclude: str +) -> List[Type[AbstractDetector]]: # If detectors are specified, run only these ones - cls_detectors_to_run = [] + cls_detectors_to_run: List[Type[AbstractDetector]] = [] exclude = detectors_to_exclude.split(",") if detectors_to_run == "all": for key, detector in all_detectors.items(): @@ -114,7 +120,7 @@ def choose_detectors(detectors_to_run, detectors_to_exclude): ################################################################################### -def print_patches(number_of_slither_results, patches): +def print_patches(number_of_slither_results: int, patches: Dict) -> None: logger.info("Number of Slither results: " + str(number_of_slither_results)) number_of_patches = 0 for file in patches: @@ -130,7 +136,7 @@ def print_patches(number_of_slither_results, patches): logger.info("Location end: " + str(patch["end"])) -def print_patches_json(number_of_slither_results, patches): +def print_patches_json(number_of_slither_results: int, patches: Dict) -> None: print("{", end="") print('"Number of Slither results":' + '"' + str(number_of_slither_results) + '",') print('"Number of patchlets":' + '"' + str(len(patches)) + '"', ",") diff --git a/slither/tools/upgradeability/__main__.py b/slither/tools/upgradeability/__main__.py index 6cc953015..414a4c175 100644 --- a/slither/tools/upgradeability/__main__.py +++ b/slither/tools/upgradeability/__main__.py @@ -3,10 +3,13 @@ import inspect import json import logging import sys +from typing import List, Any, Type, Dict, Tuple, Union, Sequence, Optional from crytic_compile import cryticparser + from slither import Slither +from slither.core.declarations import Contract from slither.exceptions import SlitherException from slither.utils.colors import red from slither.utils.output import output_to_json @@ -24,7 +27,7 @@ logger: logging.Logger = logging.getLogger("Slither") logger.setLevel(logging.INFO) -def parse_args(): +def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Slither Upgradeability Checks. For usage information see https://github.com/crytic/slither/wiki/Upgradeability-Checks.", usage="slither-check-upgradeability contract.sol ContractName", @@ -93,21 +96,27 @@ def parse_args(): ################################################################################### -def _get_checks(): - detectors = [getattr(all_checks, name) for name in dir(all_checks)] - detectors = [c for c in detectors if inspect.isclass(c) and issubclass(c, AbstractCheck)] +def _get_checks() -> List[Type[AbstractCheck]]: + detectors_ = [getattr(all_checks, name) for name in dir(all_checks)] + detectors: List[Type[AbstractCheck]] = [ + c for c in detectors_ if inspect.isclass(c) and issubclass(c, AbstractCheck) + ] return detectors class ListDetectors(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, *args, **kwargs): # pylint: disable=signature-differs + def __call__( + self, parser: Any, *args: Any, **kwargs: Any + ) -> None: # pylint: disable=signature-differs checks = _get_checks() output_detectors(checks) parser.exit() class ListDetectorsJson(argparse.Action): # pylint: disable=too-few-public-methods - def __call__(self, parser, *args, **kwargs): # pylint: disable=signature-differs + def __call__( + self, parser: Any, *args: Any, **kwargs: Any + ) -> None: # pylint: disable=signature-differs checks = _get_checks() detector_types_json = output_detectors_json(checks) print(json.dumps(detector_types_json)) @@ -116,48 +125,64 @@ class ListDetectorsJson(argparse.Action): # pylint: disable=too-few-public-meth class OutputMarkdown(argparse.Action): # pylint: disable=too-few-public-methods def __call__( - self, parser, args, values, option_string=None - ): # pylint: disable=signature-differs + self, + parser: Any, + args: Any, + values: Optional[Union[str, Sequence[Any]]], + option_string: Any = None, + ) -> None: # pylint: disable=signature-differs checks = _get_checks() + assert isinstance(values, str) output_to_markdown(checks, values) parser.exit() class OutputWiki(argparse.Action): # pylint: disable=too-few-public-methods def __call__( - self, parser, args, values, option_string=None - ): # pylint: disable=signature-differs + self, + parser: Any, + args: Any, + values: Optional[Union[str, Sequence[Any]]], + option_string: Any = None, + ) -> Any: # pylint: disable=signature-differs checks = _get_checks() + assert isinstance(values, str) output_wiki(checks, values) parser.exit() -def _run_checks(detectors): - results = [d.check() for d in detectors] - results = [r for r in results if r] - results = [item for sublist in results for item in sublist] # flatten +def _run_checks(detectors: List[AbstractCheck]) -> List[Dict]: + results_ = [d.check() for d in detectors] + results_ = [r for r in results_ if r] + results = [item for sublist in results_ for item in sublist] # flatten return results -def _checks_on_contract(detectors, contract): - detectors = [ +def _checks_on_contract( + detectors: List[Type[AbstractCheck]], contract: Contract +) -> Tuple[List[Dict], int]: + detectors_ = [ d(logger, contract) for d in detectors if (not d.REQUIRE_PROXY and not d.REQUIRE_CONTRACT_V2) ] - return _run_checks(detectors), len(detectors) + return _run_checks(detectors_), len(detectors_) -def _checks_on_contract_update(detectors, contract_v1, contract_v2): - detectors = [ +def _checks_on_contract_update( + detectors: List[Type[AbstractCheck]], contract_v1: Contract, contract_v2: Contract +) -> Tuple[List[Dict], int]: + detectors_ = [ d(logger, contract_v1, contract_v2=contract_v2) for d in detectors if d.REQUIRE_CONTRACT_V2 ] - return _run_checks(detectors), len(detectors) + return _run_checks(detectors_), len(detectors_) -def _checks_on_contract_and_proxy(detectors, contract, proxy): - detectors = [d(logger, contract, proxy=proxy) for d in detectors if d.REQUIRE_PROXY] - return _run_checks(detectors), len(detectors) +def _checks_on_contract_and_proxy( + detectors: List[Type[AbstractCheck]], contract: Contract, proxy: Contract +) -> Tuple[List[Dict], int]: + detectors_ = [d(logger, contract, proxy=proxy) for d in detectors if d.REQUIRE_PROXY] + return _run_checks(detectors_), len(detectors_) # endregion @@ -168,8 +193,8 @@ def _checks_on_contract_and_proxy(detectors, contract, proxy): ################################################################################### # pylint: disable=too-many-statements,too-many-branches,too-many-locals -def main(): - json_results = { +def main() -> None: + json_results: Dict = { "proxy-present": False, "contract_v2-present": False, "detectors": [], @@ -254,7 +279,7 @@ def main(): number_detectors_run += number_detectors # If there is a V2, we run the contract-only check on the V2 - detectors_results, _ = _checks_on_contract(detectors, v2_contract) + detectors_results, number_detectors = _checks_on_contract(detectors, v2_contract) json_results["detectors"] += detectors_results number_detectors_run += number_detectors diff --git a/slither/tools/upgradeability/utils/command_line.py b/slither/tools/upgradeability/utils/command_line.py index 6ab3f82f9..88b61ceed 100644 --- a/slither/tools/upgradeability/utils/command_line.py +++ b/slither/tools/upgradeability/utils/command_line.py @@ -1,8 +1,10 @@ -from slither.tools.upgradeability.checks.abstract_checks import classification_txt +from typing import List, Union, Dict, Type + +from slither.tools.upgradeability.checks.abstract_checks import classification_txt, AbstractCheck from slither.utils.myprettytable import MyPrettyTable -def output_wiki(detector_classes, filter_wiki): +def output_wiki(detector_classes: List[Type[AbstractCheck]], filter_wiki: str) -> None: # Sort by impact, confidence, and name detectors_list = sorted( detector_classes, key=lambda element: (element.IMPACT, element.ARGUMENT) @@ -31,7 +33,7 @@ def output_wiki(detector_classes, filter_wiki): print(recommendation) -def output_detectors(detector_classes): +def output_detectors(detector_classes: List[Type[AbstractCheck]]) -> None: detectors_list = [] for detector in detector_classes: argument = detector.ARGUMENT @@ -48,7 +50,7 @@ def output_detectors(detector_classes): for (argument, help_info, impact, proxy, v2) in detectors_list: table.add_row( [ - idx, + str(idx), argument, help_info, classification_txt[impact], @@ -60,8 +62,8 @@ def output_detectors(detector_classes): print(table) -def output_to_markdown(detector_classes, _filter_wiki): - def extract_help(cls): +def output_to_markdown(detector_classes: List[Type[AbstractCheck]], _filter_wiki: str) -> None: + def extract_help(cls: AbstractCheck) -> str: if cls.WIKI == "": return cls.HELP return f"[{cls.HELP}]({cls.WIKI})" @@ -85,7 +87,9 @@ def output_to_markdown(detector_classes, _filter_wiki): idx = idx + 1 -def output_detectors_json(detector_classes): +def output_detectors_json( + detector_classes: List[Type[AbstractCheck]], +) -> List[Dict[str, Union[str, int]]]: detectors_list = [] for detector in detector_classes: argument = detector.ARGUMENT @@ -110,7 +114,7 @@ def output_detectors_json(detector_classes): # Sort by impact, confidence, and name detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[0])) idx = 1 - table = [] + table: List[Dict[str, Union[str, int]]] = [] for ( argument, help_info, diff --git a/slither/utils/arithmetic.py b/slither/utils/arithmetic.py index 06e8956dd..18ffaec51 100644 --- a/slither/utils/arithmetic.py +++ b/slither/utils/arithmetic.py @@ -1,17 +1,12 @@ -from decimal import Decimal - from slither.exceptions import SlitherException +from slither.utils.integer_conversion import convert_string_to_fraction # pylint: disable=too-many-branches def convert_subdenomination( value: str, sub: str ) -> int: # pylint: disable=too-many-return-statements - # to allow 0.1 ether conversion - if value[0:2] == "0x": - decimal_value = Decimal(int(value, 16)) - else: - decimal_value = Decimal(value) + decimal_value = convert_string_to_fraction(value) if sub == "wei": return int(decimal_value) if sub == "gwei": diff --git a/slither/utils/colors.py b/slither/utils/colors.py index 14fc4b345..5d688489b 100644 --- a/slither/utils/colors.py +++ b/slither/utils/colors.py @@ -10,6 +10,7 @@ class Colors: # pylint: disable=too-few-public-methods YELLOW = "\033[93m" BLUE = "\033[94m" MAGENTA = "\033[95m" + BOLD = "\033[1m" END = "\033[0m" @@ -83,6 +84,7 @@ yellow = partial(colorize, Colors.YELLOW) red = partial(colorize, Colors.RED) blue = partial(colorize, Colors.BLUE) magenta = partial(colorize, Colors.MAGENTA) +bold = partial(colorize, Colors.BOLD) # We enable colorization by default if the output is a tty set_colorization_enabled(sys.stdout.isatty()) diff --git a/slither/utils/command_line.py b/slither/utils/command_line.py index d0d77c45f..c2fef5eca 100644 --- a/slither/utils/command_line.py +++ b/slither/utils/command_line.py @@ -1,13 +1,17 @@ +import argparse import json import os import re import logging from collections import defaultdict +from typing import Dict, List, Type, Union + from crytic_compile.cryticparser.defaults import ( DEFAULTS_FLAG_IN_CONFIG as DEFAULTS_FLAG_IN_CONFIG_CRYTIC_COMPILE, ) -from slither.detectors.abstract_detector import classification_txt +from slither.detectors.abstract_detector import classification_txt, AbstractDetector +from slither.printers.abstract_printer import AbstractPrinter from slither.utils.colors import yellow, red from slither.utils.myprettytable import MyPrettyTable @@ -34,7 +38,7 @@ defaults_flag_in_config = { "exclude_low": False, "exclude_medium": False, "exclude_high": False, - "fail_pedantic": False, + "fail_pedantic": True, "fail_low": False, "fail_medium": False, "fail_high": False, @@ -54,7 +58,7 @@ defaults_flag_in_config = { } -def read_config_file(args): +def read_config_file(args: argparse.Namespace) -> None: # No config file was provided as an argument if args.config_file is None: # Check wether the default config file is present @@ -83,8 +87,12 @@ def read_config_file(args): logger.error(yellow("Falling back to the default settings...")) -def output_to_markdown(detector_classes, printer_classes, filter_wiki): - def extract_help(cls): +def output_to_markdown( + detector_classes: List[Type[AbstractDetector]], + printer_classes: List[Type[AbstractPrinter]], + filter_wiki: str, +) -> None: + def extract_help(cls: Union[Type[AbstractDetector], Type[AbstractPrinter]]) -> str: if cls.WIKI == "": return cls.HELP return f"[{cls.HELP}]({cls.WIKI})" @@ -127,7 +135,7 @@ def output_to_markdown(detector_classes, printer_classes, filter_wiki): idx = idx + 1 -def get_level(l): +def get_level(l: str) -> int: tab = l.count("\t") + 1 if l.replace("\t", "").startswith(" -"): tab = tab + 1 @@ -136,7 +144,7 @@ def get_level(l): return tab -def convert_result_to_markdown(txt): +def convert_result_to_markdown(txt: str) -> str: # -1 to remove the last \n lines = txt[0:-1].split("\n") ret = [] @@ -154,16 +162,21 @@ def convert_result_to_markdown(txt): return "".join(ret) -def output_results_to_markdown(all_results, checklistlimit: str): +def output_results_to_markdown(all_results: List[Dict], checklistlimit: str) -> None: checks = defaultdict(list) - info = defaultdict(dict) - for results in all_results: - checks[results["check"]].append(results) - info[results["check"]] = {"impact": results["impact"], "confidence": results["confidence"]} + info: Dict = defaultdict(dict) + for results_ in all_results: + checks[results_["check"]].append(results_) + info[results_["check"]] = { + "impact": results_["impact"], + "confidence": results_["confidence"], + } print("Summary") - for check in checks: - print(f" - [{check}](#{check}) ({len(checks[check])} results) ({info[check]['impact']})") + for check_ in checks: + print( + f" - [{check_}](#{check_}) ({len(checks[check_])} results) ({info[check_]['impact']})" + ) counter = 0 for (check, results) in checks.items(): @@ -185,8 +198,7 @@ def output_results_to_markdown(all_results, checklistlimit: str): print(f"**More results were found, check [{checklistlimit}]({checklistlimit})**") -def output_wiki(detector_classes, filter_wiki): - detectors_list = [] +def output_wiki(detector_classes: List[Type[AbstractDetector]], filter_wiki: str) -> None: # Sort by impact, confidence, and name detectors_list = sorted( @@ -223,7 +235,7 @@ def output_wiki(detector_classes, filter_wiki): print(recommendation) -def output_detectors(detector_classes): +def output_detectors(detector_classes: List[Type[AbstractDetector]]) -> None: detectors_list = [] for detector in detector_classes: argument = detector.ARGUMENT @@ -242,12 +254,15 @@ def output_detectors(detector_classes): ) idx = 1 for (argument, help_info, impact, confidence) in detectors_list: - table.add_row([idx, argument, help_info, classification_txt[impact], confidence]) + table.add_row([str(idx), argument, help_info, classification_txt[impact], confidence]) idx = idx + 1 print(table) -def output_detectors_json(detector_classes): # pylint: disable=too-many-locals +# pylint: disable=too-many-locals +def output_detectors_json( + detector_classes: List[Type[AbstractDetector]], +) -> List[Dict]: detectors_list = [] for detector in detector_classes: argument = detector.ARGUMENT @@ -307,7 +322,7 @@ def output_detectors_json(detector_classes): # pylint: disable=too-many-locals return table -def output_printers(printer_classes): +def output_printers(printer_classes: List[Type[AbstractPrinter]]) -> None: printers_list = [] for printer in printer_classes: argument = printer.ARGUMENT @@ -319,12 +334,12 @@ def output_printers(printer_classes): printers_list = sorted(printers_list, key=lambda element: (element[0])) idx = 1 for (argument, help_info) in printers_list: - table.add_row([idx, argument, help_info]) + table.add_row([str(idx), argument, help_info]) idx = idx + 1 print(table) -def output_printers_json(printer_classes): +def output_printers_json(printer_classes: List[Type[AbstractPrinter]]) -> List[Dict]: printers_list = [] for printer in printer_classes: argument = printer.ARGUMENT diff --git a/slither/utils/function.py b/slither/utils/function.py index b86d8f4eb..34e6f221b 100644 --- a/slither/utils/function.py +++ b/slither/utils/function.py @@ -1,4 +1,4 @@ -import sha3 +from Crypto.Hash import keccak def get_function_id(sig: str) -> int: @@ -9,6 +9,6 @@ def get_function_id(sig: str) -> int: Return: (int) """ - s = sha3.keccak_256() - s.update(sig.encode("utf-8")) - return int("0x" + s.hexdigest()[:8], 16) + digest = keccak.new(digest_bits=256) + digest.update(sig.encode("utf-8")) + return int("0x" + digest.hexdigest()[:8], 16) diff --git a/slither/utils/integer_conversion.py b/slither/utils/integer_conversion.py index 8481e8641..e4dff333c 100644 --- a/slither/utils/integer_conversion.py +++ b/slither/utils/integer_conversion.py @@ -1,28 +1,35 @@ -from decimal import Decimal +from fractions import Fraction from typing import Union from slither.exceptions import SlitherError -def convert_string_to_int(val: Union[str, int]) -> int: +def convert_string_to_fraction(val: Union[str, int]) -> Fraction: if isinstance(val, int): - return val + return Fraction(val) if val.startswith(("0x", "0X")): - return int(val, 16) + return Fraction(int(val, 16)) + + # Fractions do not support underscore separators (on Python <3.11) + val = val.replace("_", "") if "e" in val or "E" in val: base, expo = val.split("e") if "e" in val else val.split("E") - base, expo = Decimal(base), int(expo) + base, expo = Fraction(base), int(expo) # The resulting number must be < 2**256-1, otherwise solc # Would not be able to compile it # 10**77 is the largest exponent that fits # See https://github.com/ethereum/solidity/blob/9e61f92bd4d19b430cb8cb26f1c7cf79f1dff380/libsolidity/ast/Types.cpp#L1281-L1290 if expo > 77: - if base != Decimal(0): + if base != Fraction(0): raise SlitherError( f"{base}e{expo} is too large to fit in any Solidity integer size" ) return 0 - return int(Decimal(base) * Decimal(10**expo)) + return Fraction(base) * Fraction(10**expo) + + return Fraction(val) - return int(Decimal(val)) + +def convert_string_to_int(val: Union[str, int]) -> int: + return int(convert_string_to_fraction(val)) diff --git a/slither/utils/output.py b/slither/utils/output.py index 6296e35d3..5db6492db 100644 --- a/slither/utils/output.py +++ b/slither/utils/output.py @@ -4,7 +4,7 @@ import json import logging import zipfile from collections import OrderedDict -from typing import Optional, Dict, List, Union, Any, TYPE_CHECKING +from typing import Optional, Dict, List, Union, Any, TYPE_CHECKING, Type from zipfile import ZipFile from pkg_resources import require @@ -129,7 +129,7 @@ def _output_result_to_sarif( def output_to_sarif( - filename: Optional[str], results: Dict, detectors_classes: List["AbstractDetector"] + filename: Optional[str], results: Dict, detectors_classes: List[Type["AbstractDetector"]] ) -> None: """ diff --git a/slither/utils/output_capture.py b/slither/utils/output_capture.py index 5282afb91..aec170d7f 100644 --- a/slither/utils/output_capture.py +++ b/slither/utils/output_capture.py @@ -28,7 +28,7 @@ class StandardOutputCapture: original_logger_handlers = None @staticmethod - def enable(block_original=True): + def enable(block_original: bool = True) -> None: """ Redirects stdout and stderr to a capturable StringIO. :param block_original: If True, blocks all output to the original stream. If False, duplicates output. @@ -54,7 +54,7 @@ class StandardOutputCapture: root_logger.handlers = [logging.StreamHandler(sys.stderr)] @staticmethod - def disable(): + def disable() -> None: """ Disables redirection of stdout/stderr, if previously enabled. :return: None @@ -78,7 +78,7 @@ class StandardOutputCapture: StandardOutputCapture.original_logger_handlers = None @staticmethod - def get_stdout_output(): + def get_stdout_output() -> str: """ Obtains the output from the currently set stdout :return: Returns stdout output as a string @@ -87,7 +87,7 @@ class StandardOutputCapture: return sys.stdout.read() @staticmethod - def get_stderr_output(): + def get_stderr_output() -> str: """ Obtains the output from the currently set stderr :return: Returns stderr output as a string diff --git a/slither/utils/type.py b/slither/utils/type.py index 1ce5fc158..5c7fcee34 100644 --- a/slither/utils/type.py +++ b/slither/utils/type.py @@ -1,12 +1,14 @@ import math -from typing import List, Union +from typing import List, Union, Set from slither.core.solidity_types import ArrayType, MappingType, ElementaryType, UserDefinedType from slither.core.solidity_types.type import Type from slither.core.variables.variable import Variable -def _convert_type_for_solidity_signature_to_string(types: Union[Type, List[Type]]) -> str: +def _convert_type_for_solidity_signature_to_string( + types: Union[Type, List[Type]], seen: Set[Type] +) -> str: if isinstance(types, Type): # Array might be struct, so we need to go again through the conversion here # We could have this logic in convert_type_for_solidity_signature @@ -15,8 +17,10 @@ def _convert_type_for_solidity_signature_to_string(types: Union[Type, List[Type] # Which is currently not supported. This comes down to (uint, uint)[] not being possible in Solidity # While having an array of a struct of two uint leads to a (uint, uint)[] signature if isinstance(types, ArrayType): - underlying_type = convert_type_for_solidity_signature(types.type) - underlying_type_str = _convert_type_for_solidity_signature_to_string(underlying_type) + underlying_type = convert_type_for_solidity_signature(types.type, seen) + underlying_type_str = _convert_type_for_solidity_signature_to_string( + underlying_type, seen + ) return underlying_type_str + "[]" return str(types) @@ -26,9 +30,9 @@ def _convert_type_for_solidity_signature_to_string(types: Union[Type, List[Type] ret = "(" for underlying_type in types: if first_item: - ret += _convert_type_for_solidity_signature_to_string(underlying_type) + ret += _convert_type_for_solidity_signature_to_string(underlying_type, seen) else: - ret += "," + _convert_type_for_solidity_signature_to_string(underlying_type) + ret += "," + _convert_type_for_solidity_signature_to_string(underlying_type, seen) first_item = False ret += ")" @@ -36,14 +40,33 @@ def _convert_type_for_solidity_signature_to_string(types: Union[Type, List[Type] def convert_type_for_solidity_signature_to_string(t: Type) -> str: - types = convert_type_for_solidity_signature(t) - return _convert_type_for_solidity_signature_to_string(types) + seen: Set[Type] = set() + types = convert_type_for_solidity_signature(t, seen) + return _convert_type_for_solidity_signature_to_string(types, seen) -def convert_type_for_solidity_signature(t: Type) -> Union[Type, List[Type]]: +def convert_type_for_solidity_signature(t: Type, seen: Set[Type]) -> Union[Type, List[Type]]: # pylint: disable=import-outside-toplevel from slither.core.declarations import Contract, Enum, Structure + # Solidity allows recursive type for structure definition if its not used in public /external + # When this happens we can reach an infinite loop. If we detect a loop, we just stop converting the underlying type + # This is ok, because it wont happen for public/external function + # + # contract A{ + # + # struct St{ + # St[] a; + # uint b; + # } + # + # function f(St memory s) internal{} + # + # } + if t in seen: + return t + seen.add(t) + if isinstance(t, UserDefinedType): underlying_type = t.type if isinstance(underlying_type, Contract): @@ -61,21 +84,24 @@ def convert_type_for_solidity_signature(t: Type) -> Union[Type, List[Type]]: if isinstance(underlying_type, Structure): # We can't have recursive types for structure, so recursion is ok here types = [ - convert_type_for_solidity_signature(x.type) for x in underlying_type.elems_ordered + convert_type_for_solidity_signature(x.type, seen) + for x in underlying_type.elems_ordered ] return types return t -def _export_nested_types_from_variable(current_type: Type, ret: List[Type]) -> None: +def _export_nested_types_from_variable( + current_type: Type, ret: List[Type], seen: Set[Type] +) -> None: """ Export the list of nested types (mapping/array) :param variable: :return: list(Type) """ if isinstance(current_type, MappingType): - underlying_type = convert_type_for_solidity_signature(current_type.type_from) + underlying_type = convert_type_for_solidity_signature(current_type.type_from, seen) if isinstance(underlying_type, list): ret.extend(underlying_type) else: @@ -87,7 +113,7 @@ def _export_nested_types_from_variable(current_type: Type, ret: List[Type]) -> N next_type = current_type.type else: return - _export_nested_types_from_variable(next_type, ret) + _export_nested_types_from_variable(next_type, ret, seen) def export_nested_types_from_variable(variable: Variable) -> List[Type]: @@ -97,7 +123,8 @@ def export_nested_types_from_variable(variable: Variable) -> List[Type]: :return: list(Type) """ l: List[Type] = [] - _export_nested_types_from_variable(variable.type, l) + seen: Set[Type] = set() + _export_nested_types_from_variable(variable.type, l, seen) return l diff --git a/slither/visitors/expression/constants_folding.py b/slither/visitors/expression/constants_folding.py index 61c98d65f..b324ed842 100644 --- a/slither/visitors/expression/constants_folding.py +++ b/slither/visitors/expression/constants_folding.py @@ -1,5 +1,5 @@ from slither.core.expressions import BinaryOperationType, Literal, UnaryOperationType -from slither.utils.integer_conversion import convert_string_to_int +from slither.utils.integer_conversion import convert_string_to_fraction, convert_string_to_int from slither.visitors.expression.expression import ExpressionVisitor @@ -72,15 +72,15 @@ class ConstantFolding(ExpressionVisitor): cf = ConstantFolding(expr, self._type) expr = cf.result() assert isinstance(expr, Literal) - set_val(expression, int(expr.value)) + set_val(expression, -convert_string_to_fraction(expr.value)) else: raise NotConstant def _post_literal(self, expression): - if expression.value.isdigit(): - set_val(expression, int(expression.value)) - else: - raise NotConstant + try: + set_val(expression, convert_string_to_fraction(expression.value)) + except ValueError as e: + raise NotConstant from e def _post_assignement_operation(self, expression): raise NotConstant @@ -115,7 +115,7 @@ class ConstantFolding(ExpressionVisitor): cf = ConstantFolding(expression.expressions[0], self._type) expr = cf.result() assert isinstance(expr, Literal) - set_val(expression, int(expr.value)) + set_val(expression, convert_string_to_fraction(expr.value)) return raise NotConstant diff --git a/tests/ast-parsing/compile/library_event-0.8.16.sol-0.8.16-compact.zip b/tests/ast-parsing/compile/library_event-0.8.16.sol-0.8.16-compact.zip new file mode 100644 index 000000000..830c0e4e8 Binary files /dev/null and b/tests/ast-parsing/compile/library_event-0.8.16.sol-0.8.16-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.0-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.0-compact.zip new file mode 100644 index 000000000..eab87a486 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.0-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.0-legacy.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.0-legacy.zip new file mode 100644 index 000000000..b5946691d Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.0-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.1-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.1-compact.zip new file mode 100644 index 000000000..3d960b6b4 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.1-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.1-legacy.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.1-legacy.zip new file mode 100644 index 000000000..c19cda479 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.1-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.2-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.2-compact.zip new file mode 100644 index 000000000..065df29b3 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.2-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.2-legacy.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.2-legacy.zip new file mode 100644 index 000000000..4f749c9ca Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.2-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.3-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.3-compact.zip new file mode 100644 index 000000000..24b6863ae Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.3-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.3-legacy.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.3-legacy.zip new file mode 100644 index 000000000..ed1aec78b Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.3-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.4-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.4-compact.zip new file mode 100644 index 000000000..bcd70d56a Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.4-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.4-legacy.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.4-legacy.zip new file mode 100644 index 000000000..4eaa1a25e Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.4-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.5-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.5-compact.zip new file mode 100644 index 000000000..1e5f938ad Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.5-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.5-legacy.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.5-legacy.zip new file mode 100644 index 000000000..daa91f7bf Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.5-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.6-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.6-compact.zip new file mode 100644 index 000000000..c69f3f426 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.6-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.6-legacy.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.6-legacy.zip new file mode 100644 index 000000000..db8047403 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.7.6-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.0-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.0-compact.zip new file mode 100644 index 000000000..9d472762d Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.0-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.1-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.1-compact.zip new file mode 100644 index 000000000..1aafa0cbe Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.1-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.10-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.10-compact.zip new file mode 100644 index 000000000..70882f214 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.10-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.11-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.11-compact.zip new file mode 100644 index 000000000..94bc29af8 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.11-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.12-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.12-compact.zip new file mode 100644 index 000000000..ffa634d55 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.12-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.13-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.13-compact.zip new file mode 100644 index 000000000..c56bc86aa Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.13-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.14-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.14-compact.zip new file mode 100644 index 000000000..d833db792 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.14-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.15-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.15-compact.zip new file mode 100644 index 000000000..466a99699 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.15-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.2-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.2-compact.zip new file mode 100644 index 000000000..59e68af7a Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.2-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.3-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.3-compact.zip new file mode 100644 index 000000000..f477ad171 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.3-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.4-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.4-compact.zip new file mode 100644 index 000000000..721779db1 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.4-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.5-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.5-compact.zip new file mode 100644 index 000000000..5bafac6b9 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.5-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.6-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.6-compact.zip new file mode 100644 index 000000000..e0358444c Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.6-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.7-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.7-compact.zip new file mode 100644 index 000000000..f9d887546 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.7-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.8-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.8-compact.zip new file mode 100644 index 000000000..ddcc81093 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.8-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.9-compact.zip b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.9-compact.zip new file mode 100644 index 000000000..ebd1e7f23 Binary files /dev/null and b/tests/ast-parsing/compile/modifier-0.7.0.sol-0.8.9-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.0-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.0-compact.zip index cfddc0391..c6e39a8f0 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.0-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.0-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.0-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.0-legacy.zip index 39d95cfe6..512e114a1 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.0-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.0-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.1-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.1-compact.zip index 69a7a8fe4..38729e076 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.1-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.1-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.1-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.1-legacy.zip index 26988bdc6..46a1a7d69 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.1-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.1-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.10-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.10-compact.zip index c816e1db5..16f0e3694 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.10-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.10-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.10-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.10-legacy.zip index c816e1db5..16f0e3694 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.10-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.10-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.11-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.11-compact.zip index eb7c8fe70..9eb504d53 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.11-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.11-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.11-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.11-legacy.zip index eb7c8fe70..9eb504d53 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.11-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.11-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.12-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.12-compact.zip index 18b5c0023..bda6fe0e3 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.12-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.12-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.12-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.12-legacy.zip index 18b5c0023..bda6fe0e3 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.12-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.12-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.13-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.13-compact.zip index 05e511d79..d0d183716 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.13-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.13-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.13-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.13-legacy.zip index 4f1ca3c92..579d9f6d0 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.13-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.13-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.14-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.14-compact.zip index db0a0f3fd..ff506a007 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.14-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.14-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.14-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.14-legacy.zip index d42f602b7..61a37cac3 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.14-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.14-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.15-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.15-compact.zip index 0483a7aab..062329dc3 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.15-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.15-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.15-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.15-legacy.zip index 547e3a7fd..148b2f868 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.15-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.15-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.16-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.16-compact.zip index 017670d1c..1259e4e03 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.16-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.16-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.16-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.16-legacy.zip index 07ae0f8be..97c4f577c 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.16-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.16-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.17-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.17-compact.zip index 66e5c9957..2106dc2cb 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.17-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.17-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.17-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.17-legacy.zip index 44bda80fa..c7c6c92cb 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.17-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.17-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.18-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.18-compact.zip index 025fafec4..8dcf47e25 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.18-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.18-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.18-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.18-legacy.zip index 2900f1013..8c756b719 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.18-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.18-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.19-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.19-compact.zip index b141c15d6..b90f8c07e 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.19-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.19-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.19-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.19-legacy.zip index 7f575de73..8c8fbab7d 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.19-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.19-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.2-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.2-compact.zip index 8bc67d877..61e616857 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.2-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.2-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.2-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.2-legacy.zip index 7c3aed134..d5d0691db 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.2-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.2-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.20-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.20-compact.zip index 9ad17df8c..7dbfd796b 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.20-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.20-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.20-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.20-legacy.zip index 35c6a0757..f2f57278f 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.20-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.20-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.21-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.21-compact.zip index 1ed1491e8..620bceadb 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.21-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.21-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.21-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.21-legacy.zip index 739750ff4..bbe5db5a4 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.21-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.21-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.22-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.22-compact.zip index 4b148ba56..6d0ac5e34 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.22-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.22-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.22-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.22-legacy.zip index c2be37ba9..ecf80602f 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.22-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.22-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.23-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.23-compact.zip index 19c1a4293..a7b910323 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.23-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.23-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.23-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.23-legacy.zip index fe5195a08..ba2050320 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.23-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.23-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.24-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.24-compact.zip index 3760c5f0b..1222d8d8d 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.24-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.24-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.24-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.24-legacy.zip index 25d4442ea..873ee11fe 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.24-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.24-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.25-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.25-compact.zip index f66a17d9a..c1b054e2e 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.25-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.25-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.25-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.25-legacy.zip index fc9d9d792..cb8cfb064 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.25-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.25-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.26-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.26-compact.zip index d46b4535b..33c4637d4 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.26-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.26-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.26-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.26-legacy.zip index 167c10fb1..426d2c8c4 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.26-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.26-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.3-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.3-compact.zip index b19bf3a39..a1086e508 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.3-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.3-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.3-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.3-legacy.zip index 14e02b8c2..66a2c1e66 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.3-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.3-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.4-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.4-compact.zip index 842c67c65..ca622d7f7 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.4-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.4-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.4-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.4-legacy.zip index 560ee388b..380b08cfc 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.4-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.4-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.5-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.5-compact.zip index 44f3dac3f..f19c5297d 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.5-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.5-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.5-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.5-legacy.zip index 6c909e4f2..0c3808e7f 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.5-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.5-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.6-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.6-compact.zip index f4407df85..ca3a1023f 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.6-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.6-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.6-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.6-legacy.zip index 8164be969..886617fd8 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.6-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.6-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.7-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.7-compact.zip index 6f439ed9e..081953928 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.7-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.7-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.7-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.7-legacy.zip index ed1708f04..f5374b523 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.7-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.7-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.8-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.8-compact.zip index 46807909d..ad369947e 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.8-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.8-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.8-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.8-legacy.zip index f90a3f74b..91de2e82a 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.8-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.8-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.9-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.9-compact.zip index b735fe419..2646618af 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.9-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.9-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.4.9-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.4.9-legacy.zip index b735fe419..2646618af 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.4.9-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.4.9-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.0-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.0-compact.zip index 75023f81a..e4ba62b56 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.0-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.0-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.0-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.0-legacy.zip index da4e7d59a..37484452a 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.0-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.0-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.1-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.1-compact.zip index 54dbdf88e..87ea809a4 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.1-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.1-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.1-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.1-legacy.zip index 5b2633e0e..af5d001c3 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.1-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.1-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.10-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.10-compact.zip index 22c051ae9..77d916a4b 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.10-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.10-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.10-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.10-legacy.zip index ee2390a86..0841d5658 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.10-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.10-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.11-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.11-compact.zip index 97cb59479..d032f2b7a 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.11-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.11-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.11-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.11-legacy.zip index a7ce558d9..0d335e734 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.11-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.11-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.12-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.12-compact.zip index 20896d7d4..5be174302 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.12-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.12-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.12-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.12-legacy.zip index 5ce65aeb8..8cab71b12 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.12-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.12-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.13-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.13-compact.zip index 484e9fd8d..8d47c01ba 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.13-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.13-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.13-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.13-legacy.zip index e3bbd21f1..9d238eedd 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.13-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.13-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.14-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.14-compact.zip index 10bbc7d75..ce2f2fee0 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.14-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.14-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.14-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.14-legacy.zip index d0125916c..a19d27957 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.14-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.14-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.15-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.15-compact.zip index 263785eb5..1cdc76aa5 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.15-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.15-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.15-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.15-legacy.zip index 27f726f89..1bb72e452 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.15-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.15-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.16-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.16-compact.zip index 9dba82dfe..d1b0b62b7 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.16-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.16-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.16-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.16-legacy.zip index 7d72a38b3..689a5c537 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.16-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.16-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.17-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.17-compact.zip index ef73090bc..ff7a96a21 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.17-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.17-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.17-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.17-legacy.zip index 1c741923a..5ac31105d 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.17-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.17-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.2-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.2-compact.zip index 74816482e..f7ab71d36 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.2-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.2-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.2-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.2-legacy.zip index 05bd06b7c..edd73a4f2 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.2-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.2-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.3-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.3-compact.zip index 11a20496d..adc49dd65 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.3-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.3-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.3-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.3-legacy.zip index 057444fbd..2d796d9d2 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.3-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.3-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.4-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.4-compact.zip index a54f0cb10..9e67e1ca4 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.4-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.4-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.4-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.4-legacy.zip index 999da3b11..b3155aa1e 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.4-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.4-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.5-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.5-compact.zip index 8ed211536..161c2c949 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.5-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.5-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.5-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.5-legacy.zip index e59d05a61..a48e14e83 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.5-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.5-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.6-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.6-compact.zip index 5a58463bf..ab38ddb1b 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.6-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.6-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.6-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.6-legacy.zip index 83de17a29..859da901f 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.6-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.6-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.7-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.7-compact.zip index 7614bb79e..6c6c20763 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.7-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.7-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.7-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.7-legacy.zip index 987af0e38..766b7c3ce 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.7-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.7-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.8-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.8-compact.zip index 7cf133ae4..71684668d 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.8-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.8-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.8-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.8-legacy.zip index 241d8b445..81f0cf7bc 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.8-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.8-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.9-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.9-compact.zip index c57077d1d..1bf4d20c7 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.9-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.9-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.5.9-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.5.9-legacy.zip index ea69f7fbf..a0b755b69 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.5.9-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.5.9-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.0-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.0-compact.zip index 2decd51e2..ef0921946 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.0-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.0-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.0-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.0-legacy.zip index d4ed5b8d1..8cc3597bb 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.0-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.0-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.1-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.1-compact.zip index a0b337bc6..0eb1ab76c 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.1-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.1-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.1-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.1-legacy.zip index 50513f8a1..fe374bfc8 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.1-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.1-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.10-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.10-compact.zip index 12fcd3893..a3242275a 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.10-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.10-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.10-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.10-legacy.zip index 99ec8d204..0d32b9295 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.10-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.10-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.11-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.11-compact.zip index daf0b8f25..f451b3b4c 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.11-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.11-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.11-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.11-legacy.zip index b59a21cdc..ec059f545 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.11-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.11-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.12-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.12-compact.zip index 5b146bee6..6c3f55506 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.12-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.12-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.12-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.12-legacy.zip index 5b4e598e3..660fee4d8 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.12-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.12-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.2-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.2-compact.zip index 25b265f54..c8505fd5e 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.2-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.2-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.2-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.2-legacy.zip index a3591a1f0..5bb2253c7 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.2-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.2-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.3-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.3-compact.zip index 29f4032aa..d69bb15d1 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.3-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.3-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.3-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.3-legacy.zip index 960422bd5..cb0ed5559 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.3-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.3-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.4-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.4-compact.zip index d236e34ca..9324b2642 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.4-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.4-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.4-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.4-legacy.zip index 28f2a0b1f..7e2fab9ca 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.4-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.4-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.5-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.5-compact.zip index ea316dc6b..475877da5 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.5-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.5-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.5-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.5-legacy.zip index cee34d9e5..2f7403ebb 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.5-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.5-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.6-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.6-compact.zip index 2a1cfe4a7..a1d38344e 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.6-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.6-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.6-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.6-legacy.zip index 7e229b641..1c1675d37 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.6-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.6-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.7-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.7-compact.zip index 530bb433e..0ee4e9521 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.7-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.7-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.7-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.7-legacy.zip index ed0510517..a58bb7027 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.7-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.7-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.8-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.8-compact.zip index 23aea0c75..cd1f9b9e6 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.8-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.8-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.8-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.8-legacy.zip index 56013943e..9366754ec 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.8-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.8-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.9-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.9-compact.zip index 7b9a86ea9..5076082d6 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.9-compact.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.9-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.6.9-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.6.9-legacy.zip index f6151d928..f91f96d4e 100644 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.6.9-legacy.zip and b/tests/ast-parsing/compile/modifier-all.sol-0.6.9-legacy.zip differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.0-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.0-compact.zip deleted file mode 100644 index cfdc87ec0..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.0-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.0-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.0-legacy.zip deleted file mode 100644 index d1113027b..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.0-legacy.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.1-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.1-compact.zip deleted file mode 100644 index b0995d507..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.1-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.1-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.1-legacy.zip deleted file mode 100644 index 377809f67..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.1-legacy.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.2-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.2-compact.zip deleted file mode 100644 index 4117212da..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.2-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.2-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.2-legacy.zip deleted file mode 100644 index 3dc1958e1..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.2-legacy.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.3-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.3-compact.zip deleted file mode 100644 index fc3c697b1..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.3-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.3-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.3-legacy.zip deleted file mode 100644 index 1936c5cf4..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.3-legacy.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.4-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.4-compact.zip deleted file mode 100644 index 819497795..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.4-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.4-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.4-legacy.zip deleted file mode 100644 index f7c156912..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.4-legacy.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.5-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.5-compact.zip deleted file mode 100644 index 45075e0bf..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.5-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.5-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.5-legacy.zip deleted file mode 100644 index 971fae4d2..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.5-legacy.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.6-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.6-compact.zip deleted file mode 100644 index 18d13d738..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.6-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.7.6-legacy.zip b/tests/ast-parsing/compile/modifier-all.sol-0.7.6-legacy.zip deleted file mode 100644 index 6b4142f33..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.7.6-legacy.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.0-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.0-compact.zip deleted file mode 100644 index 52deeb8f5..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.0-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.1-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.1-compact.zip deleted file mode 100644 index 1f5cce5c6..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.1-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.10-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.10-compact.zip deleted file mode 100644 index 26ea5c5ad..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.10-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.11-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.11-compact.zip deleted file mode 100644 index ff4b57bc4..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.11-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.12-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.12-compact.zip deleted file mode 100644 index 2d9ff7488..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.12-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.13-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.13-compact.zip deleted file mode 100644 index 7845c49f6..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.13-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.14-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.14-compact.zip deleted file mode 100644 index cdc342f12..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.14-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.15-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.15-compact.zip deleted file mode 100644 index d4d53a419..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.15-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.2-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.2-compact.zip deleted file mode 100644 index 0d7b98ce9..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.2-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.3-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.3-compact.zip deleted file mode 100644 index a1a5cb998..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.3-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.4-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.4-compact.zip deleted file mode 100644 index 33e6f9631..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.4-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.5-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.5-compact.zip deleted file mode 100644 index 6751bb8da..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.5-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.6-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.6-compact.zip deleted file mode 100644 index e6393db5c..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.6-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.7-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.7-compact.zip deleted file mode 100644 index ed7cbdfc8..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.7-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.8-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.8-compact.zip deleted file mode 100644 index 1e0c46509..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.8-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier-all.sol-0.8.9-compact.zip b/tests/ast-parsing/compile/modifier-all.sol-0.8.9-compact.zip deleted file mode 100644 index 7c12e4259..000000000 Binary files a/tests/ast-parsing/compile/modifier-all.sol-0.8.9-compact.zip and /dev/null differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.0-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.0-compact.zip index f8a3c1a16..0a7a5738d 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.0-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.0-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.1-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.1-compact.zip index cdb2a9daa..cefe498b5 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.1-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.1-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.10-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.10-compact.zip index 5fb6cde6b..8dd173562 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.10-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.10-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.11-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.11-compact.zip index adf9a336a..5b262c837 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.11-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.11-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.12-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.12-compact.zip index 7e6e7a65f..6159756b9 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.12-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.12-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.13-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.13-compact.zip index 47066aa8b..41d76763d 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.13-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.13-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.14-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.14-compact.zip index 01de606fb..eac4ef5fe 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.14-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.14-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.15-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.15-compact.zip index 233e4a87f..9db5d2399 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.15-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.15-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.2-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.2-compact.zip index b5fea85ed..4cff0e904 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.2-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.2-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.3-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.3-compact.zip index 728beb81f..c5b0b7f1a 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.3-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.3-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.4-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.4-compact.zip index 1eb88493e..fb11df4ae 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.4-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.4-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.5-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.5-compact.zip index 316ec5863..7418627bb 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.5-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.5-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.6-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.6-compact.zip index 6fd91e0e7..b157c944e 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.6-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.6-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.7-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.7-compact.zip index 041c5ea9e..a5d2432e0 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.7-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.7-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.8-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.8-compact.zip index c132ab79a..495688081 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.8-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.8-compact.zip differ diff --git a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.9-compact.zip b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.9-compact.zip index 1a06a3c57..7d915f29b 100644 Binary files a/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.9-compact.zip and b/tests/ast-parsing/compile/modifier_identifier_path.sol-0.8.9-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.0-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.0-compact.zip index b302d8129..978d4f369 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.0-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.0-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.1-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.1-compact.zip index cd27fa789..4bec78ff9 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.1-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.1-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.10-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.10-compact.zip index 5113c3465..3bb97a318 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.10-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.10-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.11-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.11-compact.zip index 51f9bfbd6..1911cca4e 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.11-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.11-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.12-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.12-compact.zip index f3ae259e8..0496870e9 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.12-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.12-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.13-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.13-compact.zip index 783d4e0ef..7fa50da53 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.13-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.13-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.14-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.14-compact.zip index a36880635..10447105b 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.14-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.14-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.15-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.15-compact.zip index cb145b39d..e7cdd8058 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.15-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.15-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.2-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.2-compact.zip index dcbfc0f06..a82c5d9a5 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.2-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.2-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.3-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.3-compact.zip index f88b7f600..d4e6e2186 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.3-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.3-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.4-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.4-compact.zip index aaeb58b19..a7821473d 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.4-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.4-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.5-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.5-compact.zip index baa3f66e7..d04e5bc71 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.5-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.5-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.6-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.6-compact.zip index 067e12293..edf1a477a 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.6-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.6-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.7-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.7-compact.zip index 1475b4e6d..564233c3f 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.7-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.7-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.8-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.8-compact.zip index f2427cdea..d972371ee 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.8-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.8-compact.zip differ diff --git a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.9-compact.zip b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.9-compact.zip index cd395e00b..f098c52a0 100644 Binary files a/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.9-compact.zip and b/tests/ast-parsing/compile/yul-0.8.0.sol-0.8.9-compact.zip differ diff --git a/tests/ast-parsing/expected/library_event-0.8.16.sol-0.8.16-compact.json b/tests/ast-parsing/expected/library_event-0.8.16.sol-0.8.16-compact.json new file mode 100644 index 000000000..0bc49a799 --- /dev/null +++ b/tests/ast-parsing/expected/library_event-0.8.16.sol-0.8.16-compact.json @@ -0,0 +1,6 @@ +{ + "Lib": {}, + "Test": { + "foo()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.0-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.0-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.0-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.0-legacy.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.0-legacy.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.0-legacy.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.1-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.1-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.1-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.1-legacy.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.1-legacy.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.1-legacy.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.2-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.2-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.2-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.2-legacy.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.2-legacy.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.2-legacy.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.3-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.3-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.3-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.3-legacy.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.3-legacy.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.3-legacy.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.4-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.4-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.4-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.4-legacy.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.4-legacy.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.4-legacy.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.5-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.5-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.5-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.5-legacy.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.5-legacy.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.5-legacy.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.6-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.6-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.6-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.6-legacy.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.6-legacy.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.7.6-legacy.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.0-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.0-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.0-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.1-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.1-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.1-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.10-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.10-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.10-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.11-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.11-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.11-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.12-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.12-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.12-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.13-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.13-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.13-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.14-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.14-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.14-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.15-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.15-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.15-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.2-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.2-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.2-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.3-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.3-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.3-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.4-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.4-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.4-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.5-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.5-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.5-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.6-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.6-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.6-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.7-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.7-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.7-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.8-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.8-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.8-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.9-compact.json b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.9-compact.json new file mode 100644 index 000000000..eaca6e24a --- /dev/null +++ b/tests/ast-parsing/expected/modifier-0.7.0.sol-0.8.9-compact.json @@ -0,0 +1,12 @@ +{ + "A": { + "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: EXPRESSION 1\n\"];\n}\n", + "m()": "digraph{\n}\n" + }, + "C": { + "onePlaceholder()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "multiplePlaceholders()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n1->2;\n2[label=\"Node Type: _ 2\n\"];\n2->3;\n3[label=\"Node Type: _ 3\n\"];\n}\n", + "acceptsVar(uint256)": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n", + "noParams()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: _ 1\n\"];\n}\n" + } +} \ No newline at end of file diff --git a/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.13-compact.json b/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.13-compact.json index c7716d2db..b58e03af7 100644 --- a/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.13-compact.json +++ b/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.13-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n", + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.14-compact.json b/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.14-compact.json index c7716d2db..b58e03af7 100644 --- a/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.14-compact.json +++ b/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.14-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n", + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.15-compact.json b/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.15-compact.json index c7716d2db..b58e03af7 100644 --- a/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.15-compact.json +++ b/tests/ast-parsing/expected/yul-0.8.0.sol-0.8.15-compact.json @@ -1,7 +1,7 @@ { "L": {}, "C": { - "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: NEW VARIABLE 16\n\"];\n16->17;\n17[label=\"Node Type: EXPRESSION 17\n\"];\n17->18;\n18[label=\"Node Type: NEW VARIABLE 18\n\"];\n18->19;\n19[label=\"Node Type: EXPRESSION 19\n\"];\n19->20;\n20[label=\"Node Type: NEW VARIABLE 20\n\"];\n20->21;\n21[label=\"Node Type: EXPRESSION 21\n\"];\n21->22;\n22[label=\"Node Type: NEW VARIABLE 22\n\"];\n22->23;\n23[label=\"Node Type: EXPRESSION 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: NEW VARIABLE 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n}\n", + "f(uint256,uint256[])": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: NEW VARIABLE 1\n\"];\n1->2;\n2[label=\"Node Type: NEW VARIABLE 2\n\"];\n2->3;\n3[label=\"Node Type: INLINE ASM 3\n\"];\n3->4;\n4[label=\"Node Type: NEW VARIABLE 4\n\"];\n4->5;\n5[label=\"Node Type: EXPRESSION 5\n\"];\n5->6;\n6[label=\"Node Type: NEW VARIABLE 6\n\"];\n6->7;\n7[label=\"Node Type: EXPRESSION 7\n\"];\n7->8;\n8[label=\"Node Type: NEW VARIABLE 8\n\"];\n8->9;\n9[label=\"Node Type: EXPRESSION 9\n\"];\n9->10;\n10[label=\"Node Type: NEW VARIABLE 10\n\"];\n10->11;\n11[label=\"Node Type: EXPRESSION 11\n\"];\n11->12;\n12[label=\"Node Type: EXPRESSION 12\n\"];\n12->13;\n13[label=\"Node Type: EXPRESSION 13\n\"];\n13->14;\n14[label=\"Node Type: EXPRESSION 14\n\"];\n14->15;\n15[label=\"Node Type: EXPRESSION 15\n\"];\n15->16;\n16[label=\"Node Type: EXPRESSION 16\n\"];\n16->17;\n17[label=\"Node Type: NEW VARIABLE 17\n\"];\n17->18;\n18[label=\"Node Type: EXPRESSION 18\n\"];\n18->19;\n19[label=\"Node Type: NEW VARIABLE 19\n\"];\n19->20;\n20[label=\"Node Type: EXPRESSION 20\n\"];\n20->21;\n21[label=\"Node Type: NEW VARIABLE 21\n\"];\n21->22;\n22[label=\"Node Type: EXPRESSION 22\n\"];\n22->23;\n23[label=\"Node Type: NEW VARIABLE 23\n\"];\n23->24;\n24[label=\"Node Type: EXPRESSION 24\n\"];\n24->25;\n25[label=\"Node Type: EXPRESSION 25\n\"];\n25->26;\n26[label=\"Node Type: EXPRESSION 26\n\"];\n26->27;\n27[label=\"Node Type: EXPRESSION 27\n\"];\n27->28;\n28[label=\"Node Type: EXPRESSION 28\n\"];\n28->29;\n29[label=\"Node Type: EXPRESSION 29\n\"];\n29->30;\n30[label=\"Node Type: NEW VARIABLE 30\n\"];\n30->31;\n31[label=\"Node Type: EXPRESSION 31\n\"];\n}\n", "f()": "digraph{\n0[label=\"Node Type: ENTRY_POINT 0\n\"];\n0->1;\n1[label=\"Node Type: INLINE ASM 1\n\"];\n1->2;\n2[label=\"Node Type: EXPRESSION 2\n\"];\n}\n" } } \ No newline at end of file diff --git a/tests/ast-parsing/library_event-0.8.16.sol b/tests/ast-parsing/library_event-0.8.16.sol new file mode 100644 index 000000000..dfb6d1d65 --- /dev/null +++ b/tests/ast-parsing/library_event-0.8.16.sol @@ -0,0 +1,12 @@ +pragma solidity 0.8.16; + +library Lib { + event Event(); +} + +contract Test { + function foo() external { + emit Lib.Event(); // This line specifically + } +} + diff --git a/tests/ast-parsing/modifier-0.7.0.sol b/tests/ast-parsing/modifier-0.7.0.sol new file mode 100644 index 000000000..24240ad5e --- /dev/null +++ b/tests/ast-parsing/modifier-0.7.0.sol @@ -0,0 +1,27 @@ +abstract contract A{ + modifier m() virtual; + + function f() public m(){ + + } +} + +contract C { + modifier onePlaceholder() { + _; + } + + modifier multiplePlaceholders() { + _; + _; + _; + } + + modifier acceptsVar(uint a) { + _; + } + + modifier noParams { + _; + } +} diff --git a/tests/ast-parsing/yul-0.8.0.sol b/tests/ast-parsing/yul-0.8.0.sol index 663c3372c..449df9135 100644 --- a/tests/ast-parsing/yul-0.8.0.sol +++ b/tests/ast-parsing/yul-0.8.0.sol @@ -70,3 +70,17 @@ function at(address _addr) view returns (bytes memory o_code) { extcodecopy(_addr, add(o_code, 0x20), 0, size) } } + + +function test(){ + + assembly { + let v + } + + assembly { + let v := "test" + } + +} + diff --git a/tests/check-upgradeability/test_10.txt b/tests/check-upgradeability/test_10.txt index 1527735c5..3d317aca5 100644 --- a/tests/check-upgradeability/test_10.txt +++ b/tests/check-upgradeability/test_10.txt @@ -10,4 +10,4 @@ Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#missing- INFO:Slither: Initializable contract not found, the contract does not follow a standard initalization schema. Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initializable-is-missing -INFO:Slither:4 findings, 18 detectors run +INFO:Slither:4 findings, 21 detectors run diff --git a/tests/check-upgradeability/test_2.txt b/tests/check-upgradeability/test_2.txt index 7641e8335..dcf910c00 100644 --- a/tests/check-upgradeability/test_2.txt +++ b/tests/check-upgradeability/test_2.txt @@ -4,4 +4,4 @@ Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initiali INFO:Slither: Initializable contract not found, the contract does not follow a standard initalization schema. Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initializable-is-missing -INFO:Slither:2 findings, 22 detectors run +INFO:Slither:2 findings, 25 detectors run diff --git a/tests/check-upgradeability/test_3.txt b/tests/check-upgradeability/test_3.txt index b3c7c0a15..fb694d5fb 100644 --- a/tests/check-upgradeability/test_3.txt +++ b/tests/check-upgradeability/test_3.txt @@ -20,4 +20,4 @@ Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#extra-va INFO:Slither: Initializable contract not found, the contract does not follow a standard initalization schema. Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initializable-is-missing -INFO:Slither:6 findings, 22 detectors run +INFO:Slither:6 findings, 25 detectors run diff --git a/tests/check-upgradeability/test_4.txt b/tests/check-upgradeability/test_4.txt index 4e32dc904..4752eb706 100644 --- a/tests/check-upgradeability/test_4.txt +++ b/tests/check-upgradeability/test_4.txt @@ -17,4 +17,4 @@ Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#extra-va INFO:Slither: Initializable contract not found, the contract does not follow a standard initalization schema. Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initializable-is-missing -INFO:Slither:5 findings, 22 detectors run +INFO:Slither:5 findings, 25 detectors run diff --git a/tests/constant_folding_rational.sol b/tests/constant_folding_rational.sol new file mode 100644 index 000000000..193133824 --- /dev/null +++ b/tests/constant_folding_rational.sol @@ -0,0 +1,9 @@ +contract C { + uint256 constant a = 2.5 + 7 + 0.5; + int128 b = 6 / 3.0; + int64 constant c = 5 * 0.5 + 0.5; + int256 d = 1e3 + 5E2; + uint256 e = 2 ** 255; + uint256 f = 115792089237316195423570985008687907853269984665640564039457584_007_913_129_639_935; + int64 constant g = -7.0; +} \ No newline at end of file diff --git a/tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol.0.4.25.DivideBeforeMultiply.json b/tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol.0.4.25.DivideBeforeMultiply.json index d164f9c60..9c2064da9 100644 --- a/tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol.0.4.25.DivideBeforeMultiply.json +++ b/tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol.0.4.25.DivideBeforeMultiply.json @@ -110,10 +110,10 @@ } } ], - "description": "A.f(uint256,uint256,uint256) (tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#2-4) performs a multiplication on the result of a division:\n\t-(a / b) * c (tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#3)\n", - "markdown": "[A.f(uint256,uint256,uint256)](tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#L2-L4) performs a multiplication on the result of a division:\n\t-[(a / b) * c](tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#L3)\n", + "description": "A.f(uint256,uint256,uint256) (tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#2-4) performs a multiplication on the result of a division:\n\t- (a / b) * c (tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#3)\n", + "markdown": "[A.f(uint256,uint256,uint256)](tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#L2-L4) performs a multiplication on the result of a division:\n\t- [(a / b) * c](tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#L3)\n", "first_markdown_element": "tests/detectors/divide-before-multiply/0.4.25/divide_before_multiply.sol#L2-L4", - "id": "fe40e2f72824d1270402b09af057ec7364af1ad2f8c48ef4df72fc27012b3186", + "id": "e0d9e5f7d421dadadf4b22750bde5233357fa2a413478117848de6e44ba9c314", "check": "divide-before-multiply", "impact": "Medium", "confidence": "Medium" diff --git a/tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol.0.5.16.DivideBeforeMultiply.json b/tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol.0.5.16.DivideBeforeMultiply.json index 6aee4f301..895721fd4 100644 --- a/tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol.0.5.16.DivideBeforeMultiply.json +++ b/tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol.0.5.16.DivideBeforeMultiply.json @@ -110,10 +110,10 @@ } } ], - "description": "A.f(uint256,uint256,uint256) (tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#2-4) performs a multiplication on the result of a division:\n\t-(a / b) * c (tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#3)\n", - "markdown": "[A.f(uint256,uint256,uint256)](tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#L2-L4) performs a multiplication on the result of a division:\n\t-[(a / b) * c](tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#L3)\n", + "description": "A.f(uint256,uint256,uint256) (tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#2-4) performs a multiplication on the result of a division:\n\t- (a / b) * c (tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#3)\n", + "markdown": "[A.f(uint256,uint256,uint256)](tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#L2-L4) performs a multiplication on the result of a division:\n\t- [(a / b) * c](tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#L3)\n", "first_markdown_element": "tests/detectors/divide-before-multiply/0.5.16/divide_before_multiply.sol#L2-L4", - "id": "a484421df5c9ebf3dc3d8bcec6701ab3065e03b21e294c4972142c4503f2fccb", + "id": "201417019df7d5dedc2b65c695ccdce8dbd171768bb64e4bae44c2b6e81bb96b", "check": "divide-before-multiply", "impact": "Medium", "confidence": "Medium" diff --git a/tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol.0.6.11.DivideBeforeMultiply.json b/tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol.0.6.11.DivideBeforeMultiply.json index 2639708b2..c250c523c 100644 --- a/tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol.0.6.11.DivideBeforeMultiply.json +++ b/tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol.0.6.11.DivideBeforeMultiply.json @@ -110,10 +110,10 @@ } } ], - "description": "A.f(uint256,uint256,uint256) (tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#2-4) performs a multiplication on the result of a division:\n\t-(a / b) * c (tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#3)\n", - "markdown": "[A.f(uint256,uint256,uint256)](tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#L2-L4) performs a multiplication on the result of a division:\n\t-[(a / b) * c](tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#L3)\n", + "description": "A.f(uint256,uint256,uint256) (tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#2-4) performs a multiplication on the result of a division:\n\t- (a / b) * c (tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#3)\n", + "markdown": "[A.f(uint256,uint256,uint256)](tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#L2-L4) performs a multiplication on the result of a division:\n\t- [(a / b) * c](tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#L3)\n", "first_markdown_element": "tests/detectors/divide-before-multiply/0.6.11/divide_before_multiply.sol#L2-L4", - "id": "9010aa3fdf8f7689d4c4d4ea0bcd771668212100e5427e48644ed7337de03a6d", + "id": "c84a7841250790acbb447d31715ca8f7818170927909d599cbc08f49ce8a665d", "check": "divide-before-multiply", "impact": "Medium", "confidence": "Medium" diff --git a/tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol.0.7.6.DivideBeforeMultiply.json b/tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol.0.7.6.DivideBeforeMultiply.json index 69310a741..7c68d8531 100644 --- a/tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol.0.7.6.DivideBeforeMultiply.json +++ b/tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol.0.7.6.DivideBeforeMultiply.json @@ -110,10 +110,10 @@ } } ], - "description": "A.f(uint256,uint256,uint256) (tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#2-4) performs a multiplication on the result of a division:\n\t-(a / b) * c (tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#3)\n", - "markdown": "[A.f(uint256,uint256,uint256)](tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#L2-L4) performs a multiplication on the result of a division:\n\t-[(a / b) * c](tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#L3)\n", + "description": "A.f(uint256,uint256,uint256) (tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#2-4) performs a multiplication on the result of a division:\n\t- (a / b) * c (tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#3)\n", + "markdown": "[A.f(uint256,uint256,uint256)](tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#L2-L4) performs a multiplication on the result of a division:\n\t- [(a / b) * c](tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#L3)\n", "first_markdown_element": "tests/detectors/divide-before-multiply/0.7.6/divide_before_multiply.sol#L2-L4", - "id": "9bc6cb85ece6cd57fa946707784180957080ad5f9575abc17af218f0d2801f77", + "id": "1978edf9df9f9dc18d8c90bb008cca4bb4b0e811fd840a337ce006fcf38c7e82", "check": "divide-before-multiply", "impact": "Medium", "confidence": "Medium" diff --git a/tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol new file mode 100644 index 000000000..854f14490 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function fopwCDKKK() public view returns (bytes32) { + return 1 == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol.0.4.25.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol.0.4.25.DomainSeparatorCollision.json new file mode 100644 index 000000000..7b89af4a8 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol.0.4.25.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "fopwCDKKK", + "source_mapping": { + "start": 5241, + "length": 150, + "filename_relative": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6181, + "filename_relative": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "fopwCDKKK()" + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK() (tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK()](tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_collision.sol#L161-L163", + "id": "cb8ae27add92ad3163cbe9c0fb29a2a0032ba46384bbd5541d1d750251f5c83e", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol new file mode 100644 index 000000000..0faf421a6 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + bytes32 public fopwCDKKK; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK, + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol.0.4.25.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol.0.4.25.DomainSeparatorCollision.json new file mode 100644 index 000000000..5d4c00817 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol.0.4.25.DomainSeparatorCollision.json @@ -0,0 +1,247 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "fopwCDKKK", + "source_mapping": { + "start": 1735, + "length": 24, + "filename_relative": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 46 + ], + "starting_column": 5, + "ending_column": 29 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6054, + "filename_relative": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK (tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol#46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK](tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol#L46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_state_var_collision.sol#L46", + "id": "8d18da367a9cfe0bee2ee48ee8a76072af23567d852cc81ed75dd90531cbe3d5", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol new file mode 100644 index 000000000..5d3401871 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function DOMAIN_SEPARATOR() public view returns (uint64) { + return uint64(1); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol.0.4.25.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol.0.4.25.DomainSeparatorCollision.json new file mode 100644 index 000000000..f5a460429 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol.0.4.25.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "DOMAIN_SEPARATOR", + "source_mapping": { + "start": 5248, + "length": 90, + "filename_relative": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6128, + "filename_relative": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "DOMAIN_SEPARATOR()" + } + } + ], + "description": "The function signature of ERC20.DOMAIN_SEPARATOR() (tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.DOMAIN_SEPARATOR()](tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.4.25/permit_domain_wrong_return_type.sol#L161-L163", + "id": "17ee24b60ef7d108871021639c374d6711feb1c8e3aad52ab266a680c03831cb", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol new file mode 100644 index 000000000..f210eaa0b --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function fopwCDKKK() public view returns (bytes32) { + return 1 == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol.0.5.16.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol.0.5.16.DomainSeparatorCollision.json new file mode 100644 index 000000000..23f93fd7e --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol.0.5.16.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "fopwCDKKK", + "source_mapping": { + "start": 5248, + "length": 150, + "filename_relative": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6188, + "filename_relative": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "fopwCDKKK()" + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK() (tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK()](tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_collision.sol#L161-L163", + "id": "cb8ae27add92ad3163cbe9c0fb29a2a0032ba46384bbd5541d1d750251f5c83e", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol new file mode 100644 index 000000000..2c63161f4 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + bytes32 public fopwCDKKK; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK, + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol.0.5.16.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol.0.5.16.DomainSeparatorCollision.json new file mode 100644 index 000000000..5cc2627ae --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol.0.5.16.DomainSeparatorCollision.json @@ -0,0 +1,247 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "fopwCDKKK", + "source_mapping": { + "start": 1735, + "length": 24, + "filename_relative": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 46 + ], + "starting_column": 5, + "ending_column": 29 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6061, + "filename_relative": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK (tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol#46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK](tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol#L46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_state_var_collision.sol#L46", + "id": "8d18da367a9cfe0bee2ee48ee8a76072af23567d852cc81ed75dd90531cbe3d5", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol new file mode 100644 index 000000000..c3f31e5f8 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function DOMAIN_SEPARATOR() public view returns (uint64) { + return uint64(1); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol.0.5.16.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol.0.5.16.DomainSeparatorCollision.json new file mode 100644 index 000000000..20ab9665d --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol.0.5.16.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "DOMAIN_SEPARATOR", + "source_mapping": { + "start": 5255, + "length": 90, + "filename_relative": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6135, + "filename_relative": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "DOMAIN_SEPARATOR()" + } + } + ], + "description": "The function signature of ERC20.DOMAIN_SEPARATOR() (tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.DOMAIN_SEPARATOR()](tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.5.16/permit_domain_wrong_return_type.sol#L161-L163", + "id": "17ee24b60ef7d108871021639c374d6711feb1c8e3aad52ab266a680c03831cb", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol new file mode 100644 index 000000000..f210eaa0b --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function fopwCDKKK() public view returns (bytes32) { + return 1 == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol.0.6.11.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol.0.6.11.DomainSeparatorCollision.json new file mode 100644 index 000000000..8bbb29bb9 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol.0.6.11.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "fopwCDKKK", + "source_mapping": { + "start": 5248, + "length": 150, + "filename_relative": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6188, + "filename_relative": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "fopwCDKKK()" + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK() (tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK()](tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_collision.sol#L161-L163", + "id": "cb8ae27add92ad3163cbe9c0fb29a2a0032ba46384bbd5541d1d750251f5c83e", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol new file mode 100644 index 000000000..2c63161f4 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + bytes32 public fopwCDKKK; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK, + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol.0.6.11.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol.0.6.11.DomainSeparatorCollision.json new file mode 100644 index 000000000..ace6f711a --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol.0.6.11.DomainSeparatorCollision.json @@ -0,0 +1,247 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "fopwCDKKK", + "source_mapping": { + "start": 1735, + "length": 24, + "filename_relative": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 46 + ], + "starting_column": 5, + "ending_column": 29 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6061, + "filename_relative": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK (tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol#46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK](tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol#L46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_state_var_collision.sol#L46", + "id": "8d18da367a9cfe0bee2ee48ee8a76072af23567d852cc81ed75dd90531cbe3d5", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol new file mode 100644 index 000000000..c3f31e5f8 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function DOMAIN_SEPARATOR() public view returns (uint64) { + return uint64(1); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol.0.6.11.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol.0.6.11.DomainSeparatorCollision.json new file mode 100644 index 000000000..7da702ba4 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol.0.6.11.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "DOMAIN_SEPARATOR", + "source_mapping": { + "start": 5255, + "length": 90, + "filename_relative": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6135, + "filename_relative": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "DOMAIN_SEPARATOR()" + } + } + ], + "description": "The function signature of ERC20.DOMAIN_SEPARATOR() (tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.DOMAIN_SEPARATOR()](tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.6.11/permit_domain_wrong_return_type.sol#L161-L163", + "id": "17ee24b60ef7d108871021639c374d6711feb1c8e3aad52ab266a680c03831cb", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol new file mode 100644 index 000000000..f210eaa0b --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function fopwCDKKK() public view returns (bytes32) { + return 1 == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol.0.7.6.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol.0.7.6.DomainSeparatorCollision.json new file mode 100644 index 000000000..6f42fc7a6 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol.0.7.6.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "fopwCDKKK", + "source_mapping": { + "start": 5248, + "length": 150, + "filename_relative": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6188, + "filename_relative": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "fopwCDKKK()" + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK() (tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK()](tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_collision.sol#L161-L163", + "id": "cb8ae27add92ad3163cbe9c0fb29a2a0032ba46384bbd5541d1d750251f5c83e", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol new file mode 100644 index 000000000..2c63161f4 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + bytes32 public fopwCDKKK; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK, + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol.0.7.6.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol.0.7.6.DomainSeparatorCollision.json new file mode 100644 index 000000000..9c246aca1 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol.0.7.6.DomainSeparatorCollision.json @@ -0,0 +1,247 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "fopwCDKKK", + "source_mapping": { + "start": 1735, + "length": 24, + "filename_relative": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 46 + ], + "starting_column": 5, + "ending_column": 29 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6061, + "filename_relative": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK (tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol#46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK](tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol#L46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_state_var_collision.sol#L46", + "id": "8d18da367a9cfe0bee2ee48ee8a76072af23567d852cc81ed75dd90531cbe3d5", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol new file mode 100644 index 000000000..5d3401871 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function DOMAIN_SEPARATOR() public view returns (uint64) { + return uint64(1); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol.0.7.6.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol.0.7.6.DomainSeparatorCollision.json new file mode 100644 index 000000000..957ae1920 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol.0.7.6.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "DOMAIN_SEPARATOR", + "source_mapping": { + "start": 5248, + "length": 90, + "filename_relative": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6128, + "filename_relative": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "DOMAIN_SEPARATOR()" + } + } + ], + "description": "The function signature of ERC20.DOMAIN_SEPARATOR() (tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.DOMAIN_SEPARATOR()](tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.7.6/permit_domain_wrong_return_type.sol#L161-L163", + "id": "17ee24b60ef7d108871021639c374d6711feb1c8e3aad52ab266a680c03831cb", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol new file mode 100644 index 000000000..04583c515 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +abstract contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public immutable decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal immutable INITIAL_CHAIN_ID; + + bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = block.chainid; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public virtual returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public virtual returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + unchecked { + balanceOf[to] += amount; + } + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public virtual returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + unchecked { + balanceOf[to] += amount; + } + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + unchecked { + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + } + + emit Approval(owner, spender, value); + } + + function fopwCDKKK() public view virtual returns (bytes32) { + return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); + } + + function computeDomainSeparator() internal view virtual returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + block.chainid, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal virtual { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + unchecked { + balanceOf[to] += amount; + } + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal virtual { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + unchecked { + totalSupply -= amount; + } + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol.0.8.0.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol.0.8.0.DomainSeparatorCollision.json new file mode 100644 index 000000000..5d6f68aa9 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol.0.8.0.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "fopwCDKKK", + "source_mapping": { + "start": 5295, + "length": 170, + "filename_relative": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6323, + "filename_relative": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "fopwCDKKK()" + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK() (tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK()](tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_collision.sol#L161-L163", + "id": "cb8ae27add92ad3163cbe9c0fb29a2a0032ba46384bbd5541d1d750251f5c83e", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol new file mode 100644 index 000000000..2c63161f4 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + bytes32 public fopwCDKKK; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) public { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + fopwCDKKK, + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol.0.8.0.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol.0.8.0.DomainSeparatorCollision.json new file mode 100644 index 000000000..dc39ccea9 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol.0.8.0.DomainSeparatorCollision.json @@ -0,0 +1,247 @@ +[ + [ + { + "elements": [ + { + "type": "variable", + "name": "fopwCDKKK", + "source_mapping": { + "start": 1735, + "length": 24, + "filename_relative": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 46 + ], + "starting_column": 5, + "ending_column": 29 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6061, + "filename_relative": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203 + ], + "starting_column": 1, + "ending_column": 2 + } + } + } + } + ], + "description": "The function signature of ERC20.fopwCDKKK (tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol#46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.fopwCDKKK](tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol#L46) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_state_var_collision.sol#L46", + "id": "8d18da367a9cfe0bee2ee48ee8a76072af23567d852cc81ed75dd90531cbe3d5", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol new file mode 100644 index 000000000..5d3401871 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) +/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) +/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. +contract ERC20 { + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event Transfer(address indexed from, address indexed to, uint256 amount); + + event Approval(address indexed owner, address indexed spender, uint256 amount); + + /*////////////////////////////////////////////////////////////// + METADATA STORAGE + //////////////////////////////////////////////////////////////*/ + + string public name; + + string public symbol; + + uint8 public decimals; + + /*////////////////////////////////////////////////////////////// + ERC20 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 public totalSupply; + + mapping(address => uint256) public balanceOf; + + mapping(address => mapping(address => uint256)) public allowance; + + /*////////////////////////////////////////////////////////////// + EIP-2612 STORAGE + //////////////////////////////////////////////////////////////*/ + + uint256 internal INITIAL_CHAIN_ID; + + bytes32 internal INITIAL_DOMAIN_SEPARATOR; + + mapping(address => uint256) public nonces; + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + constructor( + string memory _name, + string memory _symbol, + uint8 _decimals + ) { + name = _name; + symbol = _symbol; + decimals = _decimals; + + INITIAL_CHAIN_ID = 1; + INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); + } + + /*////////////////////////////////////////////////////////////// + ERC20 LOGIC + //////////////////////////////////////////////////////////////*/ + + function approve(address spender, uint256 amount) public returns (bool) { + allowance[msg.sender][spender] = amount; + + emit Approval(msg.sender, spender, amount); + + return true; + } + + function transfer(address to, uint256 amount) public returns (bool) { + balanceOf[msg.sender] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(msg.sender, to, amount); + + return true; + } + + function transferFrom( + address from, + address to, + uint256 amount + ) public returns (bool) { + uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. + + if (allowed != 115792089237316195423570985008687907853269984665640564039457584007913129639935) allowance[from][msg.sender] = allowed - amount; + + balanceOf[from] -= amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(from, to, amount); + + return true; + } + + /*////////////////////////////////////////////////////////////// + EIP-2612 LOGIC + //////////////////////////////////////////////////////////////*/ + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) public { + require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); + + // Unchecked because the only math done is incrementing + // the owner's nonce which cannot realistically overflow. + + address recoveredAddress = ecrecover( + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ) + ) + ), + v, + r, + s + ); + + require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); + + allowance[recoveredAddress][spender] = value; + + + emit Approval(owner, spender, value); + } + + function DOMAIN_SEPARATOR() public view returns (uint64) { + return uint64(1); + } + + function computeDomainSeparator() internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256(bytes(name)), + keccak256("1"), + 1, + address(this) + ) + ); + } + + /*////////////////////////////////////////////////////////////// + INTERNAL MINT/BURN LOGIC + //////////////////////////////////////////////////////////////*/ + + function _mint(address to, uint256 amount) internal { + totalSupply += amount; + + // Cannot overflow because the sum of all user + // balances can't exceed the max uint256 value. + + balanceOf[to] += amount; + + + emit Transfer(address(0), to, amount); + } + + function _burn(address from, uint256 amount) internal { + balanceOf[from] -= amount; + + // Cannot underflow because a user's balance + // will never be larger than the total supply. + + totalSupply -= amount; + + + emit Transfer(from, address(0), amount); + } +} + +contract Test is ERC20("TEST", "TEST", 18) {} diff --git a/tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol.0.8.0.DomainSeparatorCollision.json b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol.0.8.0.DomainSeparatorCollision.json new file mode 100644 index 000000000..c224777b6 --- /dev/null +++ b/tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol.0.8.0.DomainSeparatorCollision.json @@ -0,0 +1,252 @@ +[ + [ + { + "elements": [ + { + "type": "function", + "name": "DOMAIN_SEPARATOR", + "source_mapping": { + "start": 5248, + "length": 90, + "filename_relative": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 161, + 162, + 163 + ], + "starting_column": 5, + "ending_column": 6 + }, + "type_specific_fields": { + "parent": { + "type": "contract", + "name": "ERC20", + "source_mapping": { + "start": 449, + "length": 6128, + "filename_relative": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol", + "filename_absolute": "/GENERIC_PATH", + "filename_short": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol", + "is_dependency": false, + "lines": [ + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119, + 120, + 121, + 122, + 123, + 124, + 125, + 126, + 127, + 128, + 129, + 130, + 131, + 132, + 133, + 134, + 135, + 136, + 137, + 138, + 139, + 140, + 141, + 142, + 143, + 144, + 145, + 146, + 147, + 148, + 149, + 150, + 151, + 152, + 153, + 154, + 155, + 156, + 157, + 158, + 159, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 174, + 175, + 176, + 177, + 178, + 179, + 180, + 181, + 182, + 183, + 184, + 185, + 186, + 187, + 188, + 189, + 190, + 191, + 192, + 193, + 194, + 195, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205 + ], + "starting_column": 1, + "ending_column": 2 + } + }, + "signature": "DOMAIN_SEPARATOR()" + } + } + ], + "description": "The function signature of ERC20.DOMAIN_SEPARATOR() (tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol#161-163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "markdown": "The function signature of [ERC20.DOMAIN_SEPARATOR()](tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol#L161-L163) collides with DOMAIN_SEPARATOR and should be renamed or removed.\n", + "first_markdown_element": "tests/detectors/domain-separator-collision/0.8.0/permit_domain_wrong_return_type.sol#L161-L163", + "id": "17ee24b60ef7d108871021639c374d6711feb1c8e3aad52ab266a680c03831cb", + "check": "domain-separator-collision", + "impact": "Medium", + "confidence": "High" + } + ] +] \ No newline at end of file diff --git a/tests/function_ids/rec_struct-0.8.sol b/tests/function_ids/rec_struct-0.8.sol new file mode 100644 index 000000000..7440a5a33 --- /dev/null +++ b/tests/function_ids/rec_struct-0.8.sol @@ -0,0 +1,12 @@ +contract A{ + + struct St{ + St[] a; + uint b; + } + + function f(St memory s) internal{ + f(s); + } + +} diff --git a/tests/test_ast_parsing.py b/tests/test_ast_parsing.py index 506ee3d6b..e96a129b8 100644 --- a/tests/test_ast_parsing.py +++ b/tests/test_ast_parsing.py @@ -12,13 +12,13 @@ from solc_select.solc_select import installed_versions as get_installed_solc_ver from crytic_compile import CryticCompile, save_to_zip from crytic_compile.utils.zip import load_from_zip - from slither import Slither from slither.printers.guidance.echidna import Echidna SLITHER_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) TEST_ROOT = os.path.join(SLITHER_ROOT, "tests", "ast-parsing") + # pylint: disable=too-few-public-methods class Test: def __init__(self, test_file: str, solc_versions: List[str], disable_legacy: bool = False): @@ -282,7 +282,11 @@ ALL_TESTS = [ ), Test( "modifier-all.sol", - ALL_VERSIONS, + VERSIONS_04 + VERSIONS_05 + VERSIONS_06, + ), + Test( + "modifier-0.7.0.sol", + VERSIONS_07 + VERSIONS_08, ), Test("library_implicit_conversion-0.4.0.sol", VERSIONS_04), Test( @@ -420,6 +424,7 @@ ALL_TESTS = [ Test("free_functions/new_operator.sol", ["0.8.12"]), Test("free_functions/library_constant_function_collision.sol", ["0.8.12"]), Test("ternary-with-max.sol", ["0.8.15"]), + Test("library_event-0.8.16.sol", ["0.8.16"]), ] # create the output folder if needed try: diff --git a/tests/test_constant_folding.py b/tests/test_constant_folding.py new file mode 100644 index 000000000..efc3119a8 --- /dev/null +++ b/tests/test_constant_folding.py @@ -0,0 +1,45 @@ +from slither import Slither +from slither.visitors.expression.constants_folding import ConstantFolding + + +def test_constant_folding_unary(): + Slither("./tests/constant_folding_unary.sol") + + +def test_constant_folding_rational(): + s = Slither("./tests/constant_folding_rational.sol") + contract = s.get_contract_from_name("C")[0] + + variable_a = contract.get_state_variable_from_name("a") + assert str(variable_a.type) == "uint256" + assert str(ConstantFolding(variable_a.expression, "uint256").result()) == "10" + + variable_b = contract.get_state_variable_from_name("b") + assert str(variable_b.type) == "int128" + assert str(ConstantFolding(variable_b.expression, "int128").result()) == "2" + + variable_c = contract.get_state_variable_from_name("c") + assert str(variable_c.type) == "int64" + assert str(ConstantFolding(variable_c.expression, "int64").result()) == "3" + + variable_d = contract.get_state_variable_from_name("d") + assert str(variable_d.type) == "int256" + assert str(ConstantFolding(variable_d.expression, "int256").result()) == "1500" + + variable_e = contract.get_state_variable_from_name("e") + assert str(variable_e.type) == "uint256" + assert ( + str(ConstantFolding(variable_e.expression, "uint256").result()) + == "57896044618658097711785492504343953926634992332820282019728792003956564819968" + ) + + variable_f = contract.get_state_variable_from_name("f") + assert str(variable_f.type) == "uint256" + assert ( + str(ConstantFolding(variable_f.expression, "uint256").result()) + == "115792089237316195423570985008687907853269984665640564039457584007913129639935" + ) + + variable_g = contract.get_state_variable_from_name("g") + assert str(variable_g.type) == "int64" + assert str(ConstantFolding(variable_g.expression, "int64").result()) == "-7" diff --git a/tests/test_constant_folding_unary.py b/tests/test_constant_folding_unary.py deleted file mode 100644 index fa51d0934..000000000 --- a/tests/test_constant_folding_unary.py +++ /dev/null @@ -1,5 +0,0 @@ -from slither import Slither - - -def test_constant_folding_unary(): - Slither("./tests/constant_folding_unary.sol") diff --git a/tests/test_detectors.py b/tests/test_detectors.py index 796b5ff5c..f57e94803 100644 --- a/tests/test_detectors.py +++ b/tests/test_detectors.py @@ -1479,6 +1479,81 @@ ALL_TEST_OBJECTS = [ "arbitrary_send_erc20_permit.sol", "0.8.0", ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_collision.sol", + "0.4.25", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_collision.sol", + "0.5.16", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_collision.sol", + "0.6.11", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_collision.sol", + "0.7.6", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_collision.sol", + "0.8.0", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_wrong_return_type.sol", + "0.4.25", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_wrong_return_type.sol", + "0.5.16", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_wrong_return_type.sol", + "0.6.11", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_wrong_return_type.sol", + "0.7.6", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_wrong_return_type.sol", + "0.8.0", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_state_var_collision.sol", + "0.4.25", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_state_var_collision.sol", + "0.5.16", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_state_var_collision.sol", + "0.6.11", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_state_var_collision.sol", + "0.7.6", + ), + Test( + all_detectors.DomainSeparatorCollision, + "permit_domain_state_var_collision.sol", + "0.8.0", + ), ] diff --git a/tests/test_features.py b/tests/test_features.py index 88751e324..c06ee96ce 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -2,6 +2,7 @@ import inspect from crytic_compile import CryticCompile from crytic_compile.platform.solc_standard_json import SolcStandardJson +from solc_select import solc_select from slither import Slither from slither.detectors import all_detectors @@ -41,3 +42,11 @@ def test_collision(): def test_cycle(): slither = Slither("./tests/test_cyclic_import/a.sol") _run_all_detectors(slither) + + +def test_funcion_id_rec_structure(): + solc_select.switch_global_version("0.8.0", always_install=True) + slither = Slither("./tests/function_ids/rec_struct-0.8.sol") + for compilation_unit in slither.compilation_units: + for function in compilation_unit.functions: + assert function.solidity_signature diff --git a/tests/test_function.py b/tests/test_function.py index 09ecdc6ba..ef6775d64 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -15,10 +15,7 @@ def test_functions(): # pylint: disable=too-many-statements solc_select.switch_global_version("0.6.12", always_install=True) slither = Slither("tests/test_function.sol") - compilation_unit = slither.compilation_units[0] - functions = compilation_unit.get_contract_from_name("TestFunction")[ - 0 - ].available_functions_as_dict() + functions = slither.get_contract_from_name("TestFunction")[0].available_functions_as_dict() f = functions["external_payable(uint256)"] assert f.name == "external_payable" @@ -284,3 +281,17 @@ def test_reentrant(): assert not functions["internal_and_not_reentrant2()"].is_reentrant assert functions["internal_and_could_be_reentrant()"].is_reentrant assert functions["internal_and_reentrant()"].is_reentrant + + +def test_public_variable() -> None: + solc_select.switch_global_version("0.6.12", always_install=True) + slither = Slither("tests/test_function.sol") + contracts = slither.get_contract_from_name("TestFunction") + assert len(contracts) == 1 + contract = contracts[0] + var = contract.get_state_variable_from_name("info") + assert var + assert var.solidity_signature == "info()" + assert var.signature_str == "info() returns(bytes32)" + assert var.visibility == "public" + assert var.type == ElementaryType("bytes32") diff --git a/tests/test_function.sol b/tests/test_function.sol index 6ea6b9d8a..aca9fc93d 100644 --- a/tests/test_function.sol +++ b/tests/test_function.sol @@ -7,6 +7,7 @@ pragma solidity ^0.6.12; contract TestFunction { bool entered = false; + bytes32 public info; function external_payable(uint _a) external payable returns (uint) { return 1; diff --git a/tests/test_path_filtering/libs/ReentrancyMock1.sol b/tests/test_path_filtering/libs/ReentrancyMock1.sol new file mode 100644 index 000000000..9c8599081 --- /dev/null +++ b/tests/test_path_filtering/libs/ReentrancyMock1.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +contract ReentrancyMock1 { + mapping(address => uint256) public userBalances1; + + function withdraw1() external { + uint256 userBalance = userBalances1[msg.sender]; + require(userBalance > 0); + (bool success, ) = msg.sender.call{value: userBalance}(""); + require(success); + userBalances1[msg.sender] = 0; + } +} diff --git a/tests/test_path_filtering/libs/ReentrancyMock2.sol b/tests/test_path_filtering/libs/ReentrancyMock2.sol new file mode 100644 index 000000000..42b71c6a6 --- /dev/null +++ b/tests/test_path_filtering/libs/ReentrancyMock2.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +contract ReentrancyMock2 { + mapping(address => uint256) public userBalances2; + + function withdraw2() external { + uint256 userBalance = userBalances2[msg.sender]; + require(userBalance > 0); + (bool success, ) = msg.sender.call{value: userBalance}(""); + require(success); + userBalances2[msg.sender] = 0; + } +} diff --git a/tests/test_path_filtering/libs/ReentrancyMock3.sol b/tests/test_path_filtering/libs/ReentrancyMock3.sol new file mode 100644 index 000000000..097aea25a --- /dev/null +++ b/tests/test_path_filtering/libs/ReentrancyMock3.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +contract ReentrancyMock3 { + mapping(address => uint256) public userBalances3; + + function withdraw3() external { + uint256 userBalance = userBalances3[msg.sender]; + require(userBalance > 0); + (bool success, ) = msg.sender.call{value: userBalance}(""); + require(success); + userBalances3[msg.sender] = 0; + } +} diff --git a/tests/test_path_filtering/slither.config.json b/tests/test_path_filtering/slither.config.json new file mode 100644 index 000000000..95aac92b0 --- /dev/null +++ b/tests/test_path_filtering/slither.config.json @@ -0,0 +1,7 @@ +{ + "detectors_to_run": "all", + "exclude_informational": true, + "exclude_low": true, + "fail_pedantic": false, + "filter_paths": "libs|src/ReentrancyMock.sol" +} diff --git a/tests/test_path_filtering/src/ReentrancyMock.sol b/tests/test_path_filtering/src/ReentrancyMock.sol new file mode 100644 index 000000000..02d34e6ae --- /dev/null +++ b/tests/test_path_filtering/src/ReentrancyMock.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +contract ReentrancyMock { + mapping(address => uint256) public userBalances; + + function withdraw() external { + uint256 userBalance = userBalances[msg.sender]; + require(userBalance > 0); + (bool success, ) = msg.sender.call{value: userBalance}(""); + require(success); + userBalances[msg.sender] = 0; + } +} diff --git a/tests/test_path_filtering/test_path_filtering.sol b/tests/test_path_filtering/test_path_filtering.sol new file mode 100644 index 000000000..4e6859a02 --- /dev/null +++ b/tests/test_path_filtering/test_path_filtering.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import "./src/ReentrancyMock.sol"; +import "./libs/ReentrancyMock1.sol"; +import "./libs/ReentrancyMock2.sol"; +import "./libs/ReentrancyMock3.sol"; + +contract TestPathFiltering is ReentrancyMock, ReentrancyMock1, ReentrancyMock2, ReentrancyMock3 {}