Merge branch 'master' into feat/slither-conf-json-alias

This commit is contained in:
Simone
2026-07-28 17:46:50 +02:00
committed by GitHub
81 changed files with 2142 additions and 1596 deletions
+4 -4
View File
@@ -55,11 +55,11 @@ jobs:
- os: windows-2025
type: simil
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv and Python ${{ matrix.python }}
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: ${{ matrix.python }}
activate-environment: true
@@ -74,11 +74,11 @@ jobs:
- name: Set up nix
if: matrix.type == 'dapp'
uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
uses: cachix/install-nix-action@630ae543ea3a38a9a4166f03376c02c50f408342 # v31.11.0
- name: Set up cachix
if: matrix.type == 'dapp'
uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17
with:
name: dapp
+7 -7
View File
@@ -20,22 +20,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
id: buildx
with:
install: true
- name: Set Docker metadata
id: metadata
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: |
ghcr.io/${{ github.repository }}
@@ -45,16 +45,16 @@ jobs:
type=edge
- name: GitHub Container Registry Login
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4.4.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker Build and Push
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
with:
platforms: linux/amd64,linux/arm64/v8,linux/arm/v7
platforms: linux/amd64,linux/arm64
target: final
file: Dockerfile
pull: true
+5 -5
View File
@@ -28,13 +28,13 @@ jobs:
runs-on: ubuntu-slim
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup Pages
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- name: Install uv and Python
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.10"
activate-environment: true
@@ -42,10 +42,10 @@ jobs:
- run: uv sync --group doc
- run: pdoc -o html/ slither '!slither.tools' # TODO fix import errors on pdoc run
- name: Upload artifact
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
# Upload the doc
path: './html/'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
+3 -3
View File
@@ -28,17 +28,17 @@ jobs:
os: ["ubuntu-latest", "windows-2025"]
python: ["3.10", "3.14"]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python }}
- name: Install uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
+6 -6
View File
@@ -32,12 +32,12 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run Ruff linter
uses: astral-sh/ruff-action@4919ec5cf1f49eff0871dbcea0da843445b837e6 # v3
uses: astral-sh/ruff-action@278981a28ce3188b1e39527901f38254bf3aac89 # v4.1.0
with:
args: "check slither/ tests/ scripts/"
@@ -58,12 +58,12 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: true
@@ -84,12 +84,12 @@ jobs:
steps:
- name: Checkout Code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run markdownlint
uses: DavidAnson/markdownlint-cli2-action@07035fd053f7be764496c0f8d8f9f41f98305101 # v22
uses: DavidAnson/markdownlint-cli2-action@6bf21b07787794f89a243495939cd651942aeabe # v24.1.0
with:
globs: "docs/**/*.md"
config: .github/linters/.markdownlint.json
+2 -2
View File
@@ -25,12 +25,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv and Python
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.10"
enable-cache: true
+22 -11
View File
@@ -1,8 +1,9 @@
name: Publish to PyPI
on:
release:
types: [published]
push:
tags:
- '[0-9]+.[0-9]+.[0-9]+'
permissions:
contents: read
@@ -12,19 +13,19 @@ jobs:
runs-on: ubuntu-slim
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
activate-environment: true
enable-cache: true
- name: Build distributions
run: uv build
- name: Upload distributions
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: slither-dists
path: dist/
@@ -33,22 +34,32 @@ jobs:
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write # For trusted publishing + codesigning.
contents: write # For attaching signing artifacts to the release.
id-token: write # For trusted publishing, PEP 740 attestations, and sigstore signing.
contents: write # For creating the GitHub release and attaching assets.
needs:
- build-release
steps:
- name: fetch dists
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: slither-dists
path: dist/
- name: publish
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # v1.14.1
- name: sign
uses: sigstore/gh-action-sigstore-python@a5caf349bc536fbef3668a10ed7f5cd309a4b53d # v3.2.0
uses: sigstore/gh-action-sigstore-python@5b79a39c381910c090341a2c9b0bf022c8b387e1 # v3.4.0
with:
inputs: ./dist/*.tar.gz ./dist/*.whl
release-signing-artifacts: true
- name: Create GitHub release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
draft: true
name: ${{ github.ref_name }}
generate_release_notes: true
files: |
dist/*.tar.gz
dist/*.whl
dist/*.sigstore.json
+6 -6
View File
@@ -37,11 +37,11 @@ jobs:
${{ (github.event_name == 'pull_request' && fromJSON('["3.10", "3.14"]'))
|| fromJSON('["3.10", "3.11", "3.12", "3.13", "3.14"]') }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv and Python ${{ matrix.python }}
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: ${{ matrix.python }}
activate-environment: true
@@ -52,7 +52,7 @@ jobs:
uv sync --group test
- name: Setup node
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '20'
cache: 'npm'
@@ -115,11 +115,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install uv and Python
uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.10"
activate-environment: true
@@ -128,7 +128,7 @@ jobs:
- run: uv pip install coverage[toml]
- name: download coverage data
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: coverage-data-*
merge-multiple: true
+54 -55
View File
@@ -1,71 +1,70 @@
# syntax=docker/dockerfile:1.12
FROM ubuntu:jammy AS final
LABEL name=slither \
src="https://github.com/trailofbits/slither" \
creator=trailofbits \
dockerfile_maintenance=trailofbits \
desc="Static Analyzer for Solidity"
# --- Stage 1: Build ---
FROM ubuntu:noble AS builder
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
python3 python3-venv curl \
&& curl -LsSf https://astral.sh/uv/install.sh \
| UV_INSTALL_DIR=/usr/local/bin sh \
&& rm -rf /var/lib/apt/lists/*
ENV UV_LINK_MODE=copy \
UV_COMPILE_BYTECODE=1 \
UV_PYTHON_DOWNLOADS=never \
UV_PYTHON=python3.12 \
UV_PROJECT_ENVIRONMENT=/app
WORKDIR /build
# Layer 1: deps only (cached until pyproject.toml or uv.lock change)
RUN --mount=type=cache,target=/root/.cache \
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
--mount=type=bind,source=README.md,target=README.md \
uv sync --locked --no-dev --no-install-project
# Layer 2: install project (rebuilds on source changes)
COPY slither/ slither/
COPY pyproject.toml uv.lock README.md ./
RUN --mount=type=cache,target=/root/.cache \
uv sync --locked --no-dev --no-editable
# --- Stage 2: Runtime ---
FROM ubuntu:noble AS final
LABEL org.opencontainers.image.title="slither" \
org.opencontainers.image.description="Static Analyzer for Solidity" \
org.opencontainers.image.url="https://github.com/crytic/slither" \
org.opencontainers.image.source="https://github.com/crytic/slither" \
org.opencontainers.image.vendor="Trail of Bits" \
org.opencontainers.image.licenses="AGPL-3.0"
RUN export DEBIAN_FRONTEND=noninteractive \
&& apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl git python3 python3-pip python3-venv \
&& apt-get install -y --no-install-recommends python3 ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Install uv if available for this architecture (amd64/arm64)
# uv doesn't support armv7, so those builds will use pip instead
RUN arch=$(uname -m) && \
if [ "$arch" = "x86_64" ] || [ "$arch" = "aarch64" ]; then \
curl -LsSf https://astral.sh/uv/install.sh | UV_INSTALL_DIR=/usr/local/bin sh; \
fi
# improve compatibility with amd64 solc in non-amd64 environments (e.g. Docker Desktop on M1 Mac)
# Cross-arch solc compat (e.g. Docker Desktop on Apple Silicon)
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
# Install build tools only on armv7 (needed for pip to compile wheels)
# amd64/arm64 use uv with pre-built wheels, so they don't need these
RUN arch=$(uname -m) && \
if [ "$arch" = "armv7l" ]; then \
export DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y --no-install-recommends build-essential python3-dev && \
rm -rf /var/lib/apt/lists/*; \
RUN if [ "$(dpkg --print-architecture)" != "amd64" ]; 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
RUN useradd --create-home slither
USER slither
WORKDIR /home/slither
WORKDIR /home/slither/slither
# Copy dependency files first for layer caching
COPY --chown=slither:slither pyproject.toml uv.lock ./
# Install dependencies - use uv if available (with lockfile), pip otherwise
RUN if command -v uv >/dev/null 2>&1; then \
uv sync --frozen --no-install-project; \
else \
python3 -m venv .venv; \
fi
# Copy source code
COPY --chown=slither:slither . .
# Install the project itself and solc-select
RUN if command -v uv >/dev/null 2>&1; then \
uv sync --frozen && \
uv tool install solc-select; \
else \
. .venv/bin/activate && \
pip install --no-cache-dir -e . solc-select; \
fi
ENV PATH="/home/slither/slither/.venv/bin:/home/slither/.local/bin:${PATH}"
# Copy the pre-built venv from builder
COPY --from=builder --chown=slither:slither /app /app
ENV PATH="/app/bin:${PATH}"
# Pre-download latest solc so the image is ready to use
RUN solc-select use latest --always-install
CMD ["/bin/bash"]
+1 -1
View File
@@ -32,7 +32,7 @@ dependencies = [
"packaging",
"prettytable>=3.10.2",
"pycryptodome>=3.4.6",
"crytic-compile>=0.3.9,<0.4.0",
"crytic-compile>=0.4.1,<0.5.0",
"web3>=7.10,<8",
"eth-abi>=5.0.1",
"eth-typing>=5.0.0",
@@ -1,5 +1,5 @@
"""
Compute the data depenency between all the SSA variables
Compute the data dependency between all the SSA variables
"""
from typing import TYPE_CHECKING
+1 -1
View File
@@ -1094,7 +1094,7 @@ def insert_node(origin: Node, node_inserted: Node) -> None:
def recheable(node: Node) -> set[Node]:
"""
Return the set of nodes reacheable from the node
Return the set of nodes reachable from the node
:param node:
:return: set(Node)
"""
@@ -72,6 +72,8 @@ SOLIDITY_FUNCTIONS: dict[str, list[str]] = {
"log3(bytes32,bytes32,bytes32,bytes32)": [],
"blockhash(uint256)": ["bytes32"],
"prevrandao()": ["uint256"],
# Solidity 0.8.35 comptime builtin: ERC-7201 namespaced storage base slot
"erc7201(string)": ["uint256"],
# the following need a special handling
# as they are recognized as a SolidityVariableComposed
# and converted to a SolidityFunction by SlithIR
@@ -45,7 +45,7 @@ contract Constant{
uint counter;
function get() public view returns(uint){
counter = counter +1;
return counter
return counter;
}
}
```
@@ -45,7 +45,7 @@ contract Constant{
uint counter;
function get() public view returns(uint){
counter = counter +1;
return counter
return counter;
}
}
```
@@ -66,7 +66,7 @@ contract A {
"""
Detect if the IR lvalue is a vulnerable type
Must be a storage allocation, and an array of Int
Assume the IR is a InitArray, or an Assignement to an ArrayType
Assume the IR is a InitArray, or an Assignment to an ArrayType
"""
# Storage allocation
# Base type is signed integer
@@ -22,7 +22,7 @@ from slither.utils.output import Output
def _get_variables_entrance(function: FunctionContract) -> list[Any | StateIRVariable]:
"""
Return the first SSA variables of the function
Catpure the phi operation at the entry point
Capture the phi operation at the entry point
"""
ret = []
if function.entry_point:
+1 -1
View File
@@ -30,7 +30,7 @@ class DeadCode(AbstractDetector):
WIKI_EXPLOIT_SCENARIO = """
```solidity
contract Contract{
function dead_code() internal() {}
function dead_code() internal {}
}
```
`dead_code` is not used in the contract, and make the code's review more difficult."""
+4 -1
View File
@@ -17,7 +17,10 @@ from slither.utils.output import Output
def is_revert(node: Node) -> bool:
return node.type == NodeType.THROW or any(
ir.function.name in ["revert()", "revert(string"] for ir in node.internal_calls
ir.function.name == "revert()"
or ir.function.name == "revert(string)"
or ir.function.name.startswith("revert ") # SolidityCustomRevert
for ir in node.internal_calls
)
@@ -100,6 +100,11 @@ Solidity defines a [naming convention](https://solidity.readthedocs.io/en/v0.4.2
for func in contract.functions_declared:
if func.is_constructor:
continue
if func.internal_scope:
# Synthetic function defined inside inline assembly.
# Names of these functions and their parameters are
# parser-mangled artifacts, not source identifiers.
continue
if not self.is_mixed_case(func.name):
if func.visibility in [
"internal",
@@ -40,7 +40,7 @@ Only report reentrancy that acts as a double call (see `reentrancy-eth`, `reentr
if( ! (msg.sender.call()() ) ){
throw;
}
counter += 1
counter += 1;
}
```
@@ -44,7 +44,7 @@ Only report reentrancy that is based on `transfer` or `send`."""
WIKI_EXPLOIT_SCENARIO = """
```solidity
function callme(){
msg.sender.transfer(balances[msg.sender]):
msg.sender.transfer(balances[msg.sender]);
balances[msg.sender] = 0;
}
```
+1 -1
View File
@@ -112,7 +112,7 @@ contract Bug {
)
# Check named return variables
for named_return in function.returns:
# Shadowed local delcarations in the same function will have "_scope_" in their name.
# Shadowed local declarations in the same function will have "_scope_" in their name.
# See `FunctionSolc._add_local_variable`
if (
"_scope_" in variable.name
@@ -94,7 +94,7 @@ contract CallsInLoop{
If one of the destinations has a fallback function that reverts, `bad` will always revert."""
# endregion wiki_exploit_scenario
WIKI_RECOMMENDATION = "Favor [pull over push](https://github.com/ethereum/wiki/wiki/Safety#favor-pull-over-push-for-external-calls) strategy for external calls."
WIKI_RECOMMENDATION = "Favor [pull over push](https://consensysdiligence.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#favor-pull-over-push-for-external-calls) strategy for external calls."
def _detect(self) -> list[Output]:
""""""
@@ -84,6 +84,11 @@ def _explore(
divisions[ir.lvalue] = divisions[ir.rvalue] + [node] # type: ignore
else:
divisions[ir.lvalue] = divisions[ir.rvalue] # type: ignore
else:
# rvalue is not division-tainted, so the lvalue is being
# fully overwritten. Clear any stale taint left over from
# a previous division assignment to the same lvalue.
divisions.pop(ir.lvalue, None) # type: ignore
if is_division(ir):
divisions[ir.lvalue] = [node] # type: ignore
@@ -47,10 +47,14 @@ def _has_initializing_protection(functions: list[Function]) -> bool:
return False
_WHITELISTED_MODIFIERS = {"onlyProxy", "onlyDelegateCall"}
def _whitelisted_modifiers(f: Function) -> bool:
# The onlyProxy modifier prevents calling the implementation contract (must be delegatecall)
# The onlyProxy / onlyDelegateCall modifiers prevent calling the implementation contract
# directly (the call must go through delegatecall via the proxy).
# https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/3dec82093ea4a490d63aab3e925fed4f692909e8/contracts/proxy/utils/UUPSUpgradeable.sol#L38-L42
return "onlyProxy" not in [modifier.name for modifier in f.modifiers]
return not any(m.name in _WHITELISTED_MODIFIERS for m in f.modifiers)
def _initialize_functions(contract: Contract) -> list[Function]:
@@ -28,7 +28,7 @@ class UninitializedLocalVars(AbstractDetector):
contract Uninitialized is Owner{
function withdraw() payable public onlyOwner{
address to;
to.transfer(this.balance)
to.transfer(this.balance);
}
}
```
@@ -38,7 +38,7 @@ def _patch(
create_patch(
result,
in_file,
# start after the function definition's closing paranthesis
# start after the function definition's closing parenthesis
modify_loc_start + len(old_str_of_interest.decode("utf8").split(")")[0]) + 1,
# end is same as start because we insert the keyword `external` at that location
modify_loc_start + len(old_str_of_interest.decode("utf8").split(")")[0]) + 1,
+6 -2
View File
@@ -8,6 +8,7 @@ from slither.utils.output import SupportedOutput
if TYPE_CHECKING:
from slither import Slither
from slither.core.compilation_unit import SlitherCompilationUnit
class IncorrectPrinterInitialization(Exception):
@@ -20,9 +21,12 @@ class AbstractPrinter(metaclass=abc.ABCMeta):
WIKI = ""
def __init__(self, slither: "Slither", logger: Logger | None) -> None:
def __init__(
self, compilation_unit: "SlitherCompilationUnit", slither: "Slither", logger: Logger | None
) -> None:
self.compilation_unit = compilation_unit
self.slither = slither
self.contracts = slither.contracts
self.contracts = compilation_unit.contracts
self.filename = slither.filename
self.logger = logger
@@ -35,14 +35,14 @@ class PrinterInheritanceGraph(AbstractPrinter):
WIKI = "https://github.com/trailofbits/slither/wiki/Printer-documentation#inheritance-graph"
def __init__(self, slither, logger):
super().__init__(slither, logger)
def __init__(self, compilation_unit, slither, logger):
super().__init__(compilation_unit, slither, logger)
inheritance = [x.inheritance for x in slither.contracts]
inheritance = [x.inheritance for x in self.contracts]
self.inheritance = {item for sublist in inheritance for item in sublist}
self.overshadowing_state_variables = {}
shadows = detect_state_variable_shadowing(slither.contracts)
shadows = detect_state_variable_shadowing(self.contracts)
for overshadowing_instance in shadows:
overshadowing_state_var = overshadowing_instance[1]
overshadowed_state_var = overshadowing_instance[3]
+3 -3
View File
@@ -270,9 +270,9 @@ class Slither(SlitherCore):
:param printer_class: Class inheriting from `AbstractPrinter`.
"""
_check_common_things("printer", printer_class, AbstractPrinter, self._printers)
instance = printer_class(self, logger_printer)
self._printers.append(instance)
for compilation_unit in self.compilation_units:
instance = printer_class(compilation_unit, self, logger_printer)
self._printers.append(instance)
def unregister_printer(self, printer_class: type[AbstractPrinter]) -> None:
"""
@@ -145,7 +145,7 @@ def find_top_level(
# This path should be reached only after the top level custom error have been parsed
# If not, slither will crash
# It does not seem to be reacheable, but if so, we will have to adapt the order of logic
# It does not seem to be reachable, but if so, we will have to adapt the order of logic
# This must be at the end, because other top level objects might require to go over "_find_top_level"
# Before the parsing of the top level custom error
# For example, a top variable that use another top level variable
+1 -1
View File
@@ -770,7 +770,7 @@ def _parse_yul_magic_suffixes(name: str, root: YulScope) -> Expression | None:
# TODO: the following leads to wrong IR
# Currently SlithIR doesnt support raw access to memory
# So things like .offset/.slot will return the variable
# Instaed of the actual offset/slot
# Instead of the actual offset/slot
if name.endswith(("_slot", ".slot")):
potential_name = name[:-5]
variable_found = _check_for_state_variable_name(root, potential_name)
@@ -98,7 +98,10 @@ class ConstantFolding(ExpressionVisitor):
cf = ConstantFolding(expr, self._type)
expr = cf.result()
assert isinstance(expr, Literal)
set_val(expression, convert_string_to_int(expr.converted_value))
if str(expr.type) == "string":
set_val(expression, expr.converted_value)
else:
set_val(expression, convert_string_to_int(expr.converted_value))
else:
raise NotConstant
elif isinstance(expression.value, SolidityFunction):
@@ -276,6 +279,16 @@ class ConstantFolding(ExpressionVisitor):
digest = keccak.new(digest_bits=256)
digest.update(str(args[0]).encode("utf8"))
set_val(expression, digest.digest())
elif called.name == "erc7201(string)":
# Solidity 0.8.35 comptime builtin
# keccak256(keccak256(id) - 1) & ~0xff
inner = keccak.new(digest_bits=256)
inner.update(str(args[0]).encode("utf8"))
inner_int = int.from_bytes(inner.digest(), "big")
minus_one = (inner_int - 1) & ((1 << 256) - 1)
outer = keccak.new(digest_bits=256)
outer.update(minus_one.to_bytes(32, "big"))
set_val(expression, int.from_bytes(outer.digest(), "big") & ~0xFF)
else:
raise NotConstant
@@ -0,0 +1,4 @@
DivideBeforeMultiplyTest.genuineDivThenMul(uint256,uint256,uint256) (tests/e2e/detectors/test_data/divide-before-multiply/0.8.20/divide_before_multiply_reassignment.sol#32-35) performs a multiplication on the result of a division:
- a = x / y (tests/e2e/detectors/test_data/divide-before-multiply/0.8.20/divide_before_multiply_reassignment.sol#33)
- a * z (tests/e2e/detectors/test_data/divide-before-multiply/0.8.20/divide_before_multiply_reassignment.sol#34)
@@ -0,0 +1,2 @@
Modifier C.brokenNoReturn() (tests/e2e/detectors/test_data/incorrect-modifier/0.8.20/modifier_revert_variants.sol#16-21) does not always execute _; or revert
@@ -0,0 +1,2 @@
Parameter LibArr.tripwire(uint256).Bad_Param (tests/e2e/detectors/test_data/naming-convention/0.8.20/naming_convention_yul_local.sol#44) is not in mixedCase
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/// Regression coverage for the `divide-before-multiply` reassignment-kill fix.
/// `_explore`'s Assignment handler in `divide_before_multiply.py` propagates
/// taint from `rvalue` to `lvalue` when `rvalue` is itself division-tainted,
/// but never CLEARS `divisions[lvalue]` when the rvalue is a clean value.
/// So a variable that was previously the result of a division and is then
/// fully overwritten with an unrelated value still keeps its division taint,
/// and the next multiplication using it fires.
///
/// Expected output after fix: exactly one finding, for `genuineDivThenMul`
/// (the tripwire confirming the detector still catches the real bug).
contract DivideBeforeMultiplyTest {
// FP class (fix): variable reassigned to a clean value before being multiplied.
function safeReassign(uint256 x, uint256 y, uint256 z) public pure returns (uint256) {
uint256 a = x / y;
a = z; // `a` no longer holds x/y
return a * 100; // multiplies z, not a division result
}
// FP class (fix): chained reassignment through a temporary.
function safeChainedReassign(uint256 x, uint256 y, uint256 z) public pure returns (uint256) {
uint256 a = x / y;
uint256 t = z;
a = t; // taint should not propagate from a clean rvalue
return a * 100;
}
// Tripwire — the real divide-then-multiply pattern. Must still fire.
function genuineDivThenMul(uint256 x, uint256 y, uint256 z) public pure returns (uint256) {
uint256 a = x / y;
return a * z; // genuine precision loss path
}
}
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/// Regression coverage for the `incorrect-modifier` fix.
/// `if (cond) { _; } else { revert(...); }` is the structural pattern that
/// exercises the detector's `_get_false_son` walker — the walker descends into
/// the false branch and asks `is_revert(node)`. The kill-set inside `is_revert`
/// must therefore recognise every form of `revert` to avoid an FP on the four
/// "ok*" modifiers below. Only `brokenNoReturn` should be reported.
contract C {
address owner;
error NotOwner();
error NotAuthorised(address caller);
// negative case — falls off the end without reverting (genuine TP).
modifier brokenNoReturn() {
if (msg.sender == owner) {
_;
}
// no else, no revert at end -> default zero/false leaks out.
}
// existing case — `revert()` was already recognised pre-fix.
modifier okBareRevert() {
if (msg.sender == owner) {
_;
} else {
revert();
}
}
// FP class #1 (fix): `revert("string")` -> SolidityFunction("revert(string)").
modifier okStringRevert() {
if (msg.sender == owner) {
_;
} else {
revert("not owner");
}
}
// FP class #2 (fix): custom-error revert, no args -> SolidityCustomRevert("revert NotOwner()").
modifier okCustomError() {
if (msg.sender == owner) {
_;
} else {
revert NotOwner();
}
}
// FP class #3 (fix): custom-error revert, with args.
modifier okCustomErrorArgs() {
if (msg.sender == owner) {
_;
} else {
revert NotAuthorised(msg.sender);
}
}
function f1() external okBareRevert returns (uint256) { return 1; }
function f2() external okStringRevert returns (uint256) { return 2; }
function f3() external okCustomError returns (uint256) { return 3; }
function f4() external okCustomErrorArgs returns (uint256) { return 4; }
function f5() external brokenNoReturn returns (uint256) { return 5; }
}
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/// Regression coverage for the `naming-convention` fix on Yul-local functions.
/// Inline assembly can declare local functions whose parameters are mangled by
/// the parser to `<source_name>__<scope_chain>`. The detector ran its
/// mixedCase regex on the mangled name and reported FPs.
/// After the fix, functions with non-empty `internal_scope` are skipped, so
/// neither the Yul function name nor its parameters are checked.
///
/// Expected output after fix: exactly one finding, for the deliberately
/// misnamed Solidity-level parameter `Bad_Param` (the tripwire that proves
/// the detector still flags regular Solidity-level violations).
library LibArr {
function unsafeExtend(uint256[] memory base, uint256[] memory extend)
internal
pure
returns (uint256[] memory)
{
assembly ("memory-safe") {
function extendInline(base_, extend_) -> baseAfter_ {
baseAfter_ := base_
mstore(baseAfter_, add(mload(base_), mload(extend_)))
}
let res := extendInline(base, extend)
}
return base;
}
function copyBytes(bytes memory src) internal pure returns (bytes memory out) {
out = new bytes(src.length);
assembly ("memory-safe") {
function memcpy(dst_, src_, len_) {
for { let i := 0 } lt(i, len_) { i := add(i, 0x20) } {
mstore(add(dst_, i), mload(add(src_, i)))
}
}
memcpy(add(out, 0x20), add(src, 0x20), mload(src))
}
}
// Tripwire — a Solidity-level parameter using snake_case must still fire.
function tripwire(uint256 Bad_Param) internal pure returns (uint256) {
return Bad_Param;
}
}
@@ -0,0 +1,5 @@
contract OnlyDelegateCall {
modifier onlyDelegateCall() {
_;
}
}
@@ -1,5 +1,6 @@
import "./Initializable.sol";
import "./OnlyProxy.sol";
import "./OnlyDelegateCall.sol";
contract Whitelisted is Initializable, OnlyProxy{
address owner;
@@ -13,3 +14,16 @@ contract Whitelisted is Initializable, OnlyProxy{
selfdestruct(owner);
}
}
contract WhitelistedDelegateCall is Initializable, OnlyDelegateCall{
address owner;
function initialize() external initializer onlyDelegateCall {
owner = msg.sender;
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}
@@ -0,0 +1,5 @@
contract OnlyDelegateCall {
modifier onlyDelegateCall() {
_;
}
}
@@ -1,5 +1,6 @@
import "./Initializable.sol";
import "./OnlyProxy.sol";
import "./OnlyDelegateCall.sol";
contract Whitelisted is Initializable, OnlyProxy{
address payable owner;
@@ -13,3 +14,16 @@ contract Whitelisted is Initializable, OnlyProxy{
selfdestruct(owner);
}
}
contract WhitelistedDelegateCall is Initializable, OnlyDelegateCall{
address payable owner;
function initialize() external initializer onlyDelegateCall {
owner = msg.sender;
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}
@@ -0,0 +1,5 @@
contract OnlyDelegateCall {
modifier onlyDelegateCall() {
_;
}
}
@@ -1,5 +1,6 @@
import "./Initializable.sol";
import "./OnlyProxy.sol";
import "./OnlyDelegateCall.sol";
contract Whitelisted is Initializable, OnlyProxy{
address payable owner;
@@ -13,3 +14,16 @@ contract Whitelisted is Initializable, OnlyProxy{
selfdestruct(owner);
}
}
contract WhitelistedDelegateCall is Initializable, OnlyDelegateCall{
address payable owner;
function initialize() external initializer onlyDelegateCall {
owner = msg.sender;
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}
@@ -0,0 +1,5 @@
contract OnlyDelegateCall {
modifier onlyDelegateCall() {
_;
}
}
@@ -1,5 +1,6 @@
import "./Initializable.sol";
import "./OnlyProxy.sol";
import "./OnlyDelegateCall.sol";
contract Whitelisted is Initializable, OnlyProxy{
address payable owner;
@@ -13,3 +14,16 @@ contract Whitelisted is Initializable, OnlyProxy{
selfdestruct(owner);
}
}
contract WhitelistedDelegateCall is Initializable, OnlyDelegateCall{
address payable owner;
function initialize() external initializer onlyDelegateCall {
owner = msg.sender;
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}
@@ -0,0 +1,5 @@
contract OnlyDelegateCall {
modifier onlyDelegateCall() {
_;
}
}
@@ -1,5 +1,6 @@
import "./Initializable.sol";
import "./OnlyProxy.sol";
import "./OnlyDelegateCall.sol";
contract Whitelisted is Initializable, OnlyProxy{
address payable owner;
@@ -13,3 +14,16 @@ contract Whitelisted is Initializable, OnlyProxy{
selfdestruct(owner);
}
}
contract WhitelistedDelegateCall is Initializable, OnlyDelegateCall{
address payable owner;
function initialize() external initializer onlyDelegateCall {
owner = payable(msg.sender);
}
function kill() external {
require(msg.sender == owner);
selfdestruct(owner);
}
}
+15
View File
@@ -639,6 +639,11 @@ ALL_TESTS = [
"no_warning_for_public_constants.sol",
"0.7.6",
),
Test(
all_detectors.NamingConvention,
"naming_convention_yul_local.sol",
"0.8.20",
),
Test(
all_detectors.ControlledDelegateCall,
"controlled_delegatecall.sol",
@@ -1326,6 +1331,11 @@ ALL_TESTS = [
"modifier_default.sol",
"0.7.6",
),
Test(
all_detectors.ModifierDefaultDetection,
"modifier_revert_variants.sol",
"0.8.20",
),
Test(
all_detectors.IncorrectUnaryExpressionDetection,
"invalid_unary_expression.sol",
@@ -1447,6 +1457,11 @@ ALL_TESTS = [
"divide_before_multiply.sol",
"0.7.6",
),
Test(
all_detectors.DivideBeforeMultiply,
"divide_before_multiply_reassignment.sol",
"0.8.20",
),
Test(
all_detectors.TypeBasedTautology,
"type_based_tautology.sol",
@@ -1,3 +1,4 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
Target functions:
- A.destination()
+19 -6
View File
@@ -31,7 +31,10 @@ def test_inheritance_graph_printer(solc_binary_path) -> None:
standard_json.add_source_file(Path(TEST_DATA_DIR, "test_contract_names", "C.sol").as_posix())
compilation = CryticCompile(standard_json, solc=solc_path)
slither = Slither(compilation)
printer = PrinterInheritanceGraph(slither=slither, logger=None)
# Use register_printer to properly handle multiple compilation units
slither.register_printer(PrinterInheritanceGraph)
assert len(slither._printers) > 0
printer = slither._printers[0]
output = printer.output("test_printer.dot")
content = output.elements[0]["name"]["content"]
@@ -67,7 +70,9 @@ def test_printer_cheatcode():
foundry_compile_all=True,
)
printer = CheatcodePrinter(slither=slither, logger=None)
slither.register_printer(CheatcodePrinter)
assert len(slither._printers) > 0
printer = slither._printers[0]
output = printer.output("")
assert (
@@ -85,7 +90,9 @@ def test_slithir_printer(solc_binary_path) -> None:
compilation = CryticCompile(standard_json, solc=solc_path)
slither = Slither(compilation)
printer = PrinterSlithIR(slither, logger=None)
slither.register_printer(PrinterSlithIR)
assert len(slither._printers) > 0
printer = slither._printers[0]
output = printer.output("test_printer_slithir.dot")
assert "slither.core.solidity_types" not in output.data["description"]
@@ -102,7 +109,9 @@ def test_inheritance_text_printer(solc_binary_path) -> None:
compilation = CryticCompile(standard_json, solc=solc_path)
slither = Slither(compilation)
printer = PrinterInheritance(slither=slither, logger=None)
slither.register_printer(PrinterInheritance)
assert len(slither._printers) > 0
printer = slither._printers[0]
output = printer.output("test_inheritance.txt")
# Data is nested under additional_fields
@@ -140,7 +149,9 @@ def test_callgraph_printer_toplevel(solc_binary_path) -> None:
compilation = CryticCompile(standard_json, solc=solc_path)
slither = Slither(compilation)
printer = PrinterCallGraph(slither, logger=None)
slither.register_printer(PrinterCallGraph)
assert len(slither._printers) > 0
printer = slither._printers[0]
output = printer.output("test_callgraph_toplevel")
content = output.elements[0]["name"]["content"]
@@ -183,7 +194,9 @@ def test_c3_linearization_printer(solc_binary_path) -> None:
compilation = CryticCompile(standard_json, solc=solc_path)
slither = Slither(compilation)
printer = PrinterC3Linearization(slither=slither, logger=None)
slither.register_printer(PrinterC3Linearization)
assert len(slither._printers) > 0
printer = slither._printers[0]
output = printer.output("")
# Check that all contracts are present in the output
+1
View File
@@ -1,3 +1,4 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
# Check ERC20
## Check functions
+1
View File
@@ -1,3 +1,4 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
## Check for functions coverage
[✓] SafeAdd.add(uint256,uint256)
@@ -1,5 +1,7 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
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
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:1 findings, 12 detectors run
@@ -1,7 +1,9 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
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
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: became-constant
ContractV1.destination (tests/tools/check_upgradeability/contractV1.sol#2) was not constant but ContractV2.destination (tests/tools/check_upgradeability/contract_v2_constant.sol#2) is.
@@ -1,3 +1,4 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
Initializable contract not found, the contract does not follow a standard initalization schema.
@@ -1,7 +1,9 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
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
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
Initializable contract not found, the contract does not follow a standard initalization schema.
@@ -1,7 +1,9 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
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
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: order-vars-contracts
Different variables between ContractV1 (tests/tools/check_upgradeability/contractV1_struct.sol#1-8) and ContractV2 (tests/tools/check_upgradeability/contractV2_struct_bug.sol#1-8)
@@ -1,5 +1,7 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: initialize-target
Contract_no_bug_reinitializer (tests/tools/check_upgradeability/contract_initialization.sol#23-29) needs to be initialized by Contract_no_bug_reinitializer.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#25-27).
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initialize-function
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:1 findings, 12 detectors run
@@ -1,3 +1,4 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: initialize-target
Contract_reinitializer_V2 (tests/tools/check_upgradeability/contract_initialization.sol#63-77) needs to be initialized by Contract_reinitializer_V2.initialize(uint256) (tests/tools/check_upgradeability/contract_initialization.sol#66-68).
@@ -1,7 +1,10 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
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
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
Initializable contract not found, the contract does not follow a standard initalization schema.
@@ -1,7 +1,10 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
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
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: order-vars-proxy
Different variables between ContractV2 (tests/tools/check_upgradeability/contractV2_bug.sol#1-5) and Proxy (tests/tools/check_upgradeability/proxy.sol#7-27)
@@ -1,7 +1,10 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: init-missing
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
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: order-vars-proxy
Different variables between ContractV2 (tests/tools/check_upgradeability/contractV2_bug2.sol#4-6) and Proxy (tests/tools/check_upgradeability/proxy.sol#7-27)
@@ -1,5 +1,7 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: initialize-target
Contract_no_bug (tests/tools/check_upgradeability/contract_initialization.sol#15-21) needs to be initialized by Contract_no_bug.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#17-19).
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initialize-function
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:1 findings, 12 detectors run
@@ -1,3 +1,4 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: initialize-target
Contract_lack_to_call_modifier (tests/tools/check_upgradeability/contract_initialization.sol#31-36) needs to be initialized by Contract_lack_to_call_modifier.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#33-35).
@@ -6,4 +7,5 @@ INFO:Slither:
Detector: missing-init-modifier
Contract_lack_to_call_modifier.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#33-35) does not call the initializer or reinitializer modifier.
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initializer-is-not-called
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:2 findings, 12 detectors run
@@ -1,3 +1,4 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: initialize-target
Contract_not_called_super_init (tests/tools/check_upgradeability/contract_initialization.sol#38-44) needs to be initialized by Contract_not_called_super_init.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#40-42).
@@ -6,4 +7,5 @@ INFO:Slither:
Detector: missing-calls
Missing call to Contract_no_bug.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#17-19) in Contract_not_called_super_init.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#40-42).
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initialize-functions-are-not-called
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:2 findings, 12 detectors run
@@ -1,5 +1,7 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: initialize-target
Contract_no_bug_inherits (tests/tools/check_upgradeability/contract_initialization.sol#46-52) needs to be initialized by Contract_no_bug_inherits.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#48-50).
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initialize-function
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:1 findings, 12 detectors run
@@ -1,3 +1,4 @@
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:
Detector: initialize-target
Contract_double_call (tests/tools/check_upgradeability/contract_initialization.sol#54-61) needs to be initialized by Contract_double_call.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#56-59).
@@ -6,4 +7,5 @@ INFO:Slither:
Detector: multiple-calls
Contract_no_bug.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#17-19) is called multiple times in Contract_double_call.initialize() (tests/tools/check_upgradeability/contract_initialization.sol#56-59).
Reference: https://github.com/crytic/slither/wiki/Upgradeability-Checks#initialize-functions-are-called-multiple-times
WARNING:CryticCompile:Multiple frameworks detected: solc, Solc-json. Using solc (highest priority). Use --compile-force-framework to override.
INFO:Slither:2 findings, 12 detectors run
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.35;
string constant NS = "openzeppelin.storage.MyContract";
contract MyContract layout at erc7201(NS) {
uint256 x;
uint256 y;
}
+5
View File
@@ -15,6 +15,11 @@ def test_custom_storage_layout(solc_binary_path):
_test_storage_layout(solc_binary_path, "0.8.33", "storage_layout-0.8.33.sol")
def test_erc7201_storage_layout(solc_binary_path):
# 0.8.35 erc7201 comptime builtin used as the base slot of `layout at`
_test_storage_layout(solc_binary_path, "0.8.35", "storage_layout-0.8.35.sol")
def _test_storage_layout(solc_binary_path, solc_version, test_file):
# the storage layout has not yet changed between solidity versions so we will test with one version of the compiler
solc_path = solc_binary_path(solc_version)
Generated
+1636 -1462
View File
File diff suppressed because it is too large Load Diff