mirror of
https://github.com/crytic/slither.git
synced 2026-10-12 02:12:39 +00:00
Merge branch 'master' into feat/slither-conf-json-alias
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+4
@@ -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)
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
+36
@@ -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
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
@@ -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; }
|
||||
}
|
||||
BIN
Binary file not shown.
+47
@@ -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;
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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()
|
||||
|
||||
|
||||
@@ -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,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,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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user