diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9cab5db --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +# Ignore all files by default. +** + +# Include only the main script. +!safe_hashes.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03dc47c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Ignore the `data` directory by default. +data/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..15683e3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +# For reproducible builds, consider pinning to a specific digest instead of `latest`. +# See https://github.com/foundry-rs/foundry/pkgs/container/foundry. +FROM ghcr.io/foundry-rs/foundry:latest + +# Switch to the root user to install the necessary packages. +USER root + +# Install `curl` and `jq` using the package manager. +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + curl \ + jq \ + && rm -rf /var/lib/apt/lists/* + +# Copy the script into the image. +COPY ./safe_hashes.sh /app/safe_hashes.sh +RUN chmod +x /app/safe_hashes.sh + +# Switch back to the default, non-root Foundry user for security. +USER foundry diff --git a/README.md b/README.md index 862efe6..c83b475 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,11 @@ This Bash [script](./safe_hashes.sh) calculates the Safe transaction hashes by r - [Usage](#usage) - [macOS Users: Upgrading Bash](#macos-users-upgrading-bash) - [Optional: Set the New Bash as Your Default Shell](#optional-set-the-new-bash-as-your-default-shell) + - [Docker Usage](#docker-usage) + - [Building the Docker Image](#building-the-docker-image) + - [Basic Usage](#basic-usage) + - [Using Message Files](#using-message-files) + - [With Environment Variables](#with-environment-variables) - [Safe Transaction Hashes](#safe-transaction-hashes) - [Interactive Mode](#interactive-mode) - [Transaction Simulation](#transaction-simulation) @@ -81,7 +86,7 @@ This Bash [script](./safe_hashes.sh) calculates the Safe transaction hashes by r > Ensure that [`cast`](https://github.com/foundry-rs/foundry/tree/master/crates/cast) and [`chisel`](https://github.com/foundry-rs/foundry/tree/master/crates/chisel) are installed locally. For installation instructions, refer to this [guide](https://getfoundry.sh/introduction/installation/). This [script](./safe_hashes.sh) is designed to work with the latest _stable_ versions of [`cast`](https://github.com/foundry-rs/foundry/tree/master/crates/cast) and [`chisel`](https://github.com/foundry-rs/foundry/tree/master/crates/chisel), starting from version [`1.3.5`](https://github.com/foundry-rs/foundry/releases/tag/v1.3.5). > [!TIP] -> For macOS users, please refer to the [macOS Users: Upgrading Bash](#macos-users-upgrading-bash) section. +> For macOS users, please refer to the [macOS Users: Upgrading Bash](#macos-users-upgrading-bash) section. Alternatively, you can use the Docker container, which comes pre-installed with all required dependencies. For details, see the [Docker Usage](#docker-usage) section below. ```console ./safe_hashes.sh [--help] [--version] [--list-networks] --network --address
@@ -199,6 +204,65 @@ chsh -s BASH_PATH Make sure to replace `BASH_PATH` with the actual path you retrieved in step 1. +### Docker Usage + +Using [Docker](https://www.docker.com), you can run the [script](./safe_hashes.sh) in a containerised environment with all dependencies pre-installed. This is useful if you do not wish to install the required tools locally, or if you are on a system where installation is difficult. + +#### Building the Docker Image + +Build the [Docker](https://www.docker.com) image using [Docker Compose](https://docs.docker.com/compose/): + +```console +docker-compose build +``` + +#### Basic Usage + +To run the [script](./safe_hashes.sh) using [Docker Compose](https://docs.docker.com/compose/), use the [`compose.yaml`](./compose.yaml) file provided in the repository. The container is named `safe-tx-hashes-util`. + +Example displaying help: + +```console +docker-compose run --rm safe-tx-hashes-util --help +``` + +Example calculating the Safe transaction hashes: + +```console +docker-compose run --rm safe-tx-hashes-util --network arbitrum --address 0x111CEEee040739fD91D29C34C33E6B3E112F2177 --nonce 234 +``` + +#### Using Message Files + +When calculating off-chain message hashes, you need to provide a local directory containing your message file. The included [`compose.yaml`](./compose.yaml) configuration mounts the `./data` directory by default. + +```console +# First, create a `data` directory and add your message file. +~$ mkdir -p data +~$ echo "Your message content here" > data/message.txt + +# Run the container with the mounted directory. +~$ docker-compose run --rm safe-tx-hashes-util \ + --network sepolia \ + --address 0x657ff0D4eC65D82b2bC1247b0a558bcd2f80A0f1 \ + --message /data/message.txt +``` + +#### With Environment Variables + +You can pass environment variables directly via [Docker Compose](https://docs.docker.com/compose/): + +```console +# Disable all formatting. +docker-compose run --rm -e NO_COLOR=true safe-tx-hashes-util \ + --network arbitrum \ + --address 0x111CEEee040739fD91D29C34C33E6B3E112F2177 \ + --nonce 234 +``` + +> [!IMPORTANT] +> Running in a [Docker](https://www.docker.com) container offers isolation, but it is important to always follow the [Security Best Practices](#security-best-practices-for-using-this-script). + ## Safe Transaction Hashes To calculate the Safe transaction hashes for a specific transaction, you need to specify the `network`, `address`, and `nonce` parameters. An example: diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..551f416 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,46 @@ +services: + safe-tx-hashes-util: + build: + context: . + dockerfile: Dockerfile + + container_name: safe-tx-hashes-util + + security_opt: + - no-new-privileges:true # Prevent privilege escalation. + - apparmor=docker-default # Set the `AppArmor` profile for Ubuntu/Debian/openSUSE (restrict file/network access). + - label=type:container_t # Set the `SELinux` profile for RHEL/CentOS/Fedora (provide mandatory access control). + + cap_drop: + - ALL # Drop all root Linux kernel capabilities. + + read_only: true # Make the container's root filesystem read-only. + + working_dir: /app + + volumes: + # Mount the script from the host for live editing without rebuilding the image. + - type: bind + source: ./safe_hashes.sh + target: /app/safe_hashes.sh + read_only: true + # Mount the host `./data` directory as read-only for off-chain message files. + - type: bind + source: ./data + target: /data + read_only: true + bind: + create_host_path: true + + tmpfs: + - /tmp:noexec,nosuid,nodev,size=50m # Store temporary files in memory only (limited to 50MB, not executable). + - /home/foundry/.foundry:noexec,nosuid,nodev,size=50m # Keep Foundry's cache and settings in memory (limited to 50MB, cannot run programs from here). + - /home/foundry/.svm:exec,nosuid,nodev,size=50m # Keep Solidity Version Manager (`svm`) files in memory (limited to 50MB, programs can run from here). + + environment: + - DEBUG=false # See https://github.com/pcaversaccio/safe-tx-hashes-util/tree/main#usage. + - NO_COLOR=false # See https://github.com/pcaversaccio/safe-tx-hashes-util/tree/main#usage. + - FOUNDRY_DISABLE_NIGHTLY_WARNING=false + + # Override the image's default command to run the script. + entrypoint: ["/bin/bash", "/app/safe_hashes.sh"]