diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..debc20c5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[Makefile] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false + +[*.ps1] +end_of_line = crlf diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f30df379 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,16 @@ +* text=auto + +.editorconfig text eol=lf +.gitattributes text eol=lf +.gitignore text eol=lf + +*.sol text eol=lf +*.md text eol=lf +*.toml text eol=lf +*.txt text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.sh text eol=lf +Makefile text eol=lf + +*.ps1 text eol=crlf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..9ed5fea0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,46 @@ +name: CI + +on: + pull_request: + push: + branches: + - main + +jobs: + foundry: + name: Foundry smoke + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 + with: + persist-credentials: false + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@c7450ba673e133f5ee30098b3b54f444d3a2ca2d + with: + version: v1.7.1 + + - name: Build + shell: bash + run: | + set -o pipefail + mkdir -p ci-logs + forge build 2>&1 | tee ci-logs/forge-build.log + + - name: Test + shell: bash + run: | + set -o pipefail + mkdir -p ci-logs + forge test -vvv 2>&1 | tee ci-logs/forge-test.log + + - name: Upload Foundry logs + if: always() + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 + with: + name: foundry-smoke-logs + path: ci-logs/ + if-no-files-found: ignore + retention-days: 14 diff --git a/.gitignore b/.gitignore index 6153de11..b108de07 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,27 @@ -# Ignore node_modules directory +# Node / frontend artifacts node_modules/ -# Ignore log files +# Logs logs/ *.log -# Ignore build directories +# Build outputs dist/ build/ +out/ +cache/ +broadcast/ -# Ignore environment variable files +# Local environments and secrets .env +.env.* +!.env.example +!.env.sample +!.env.template +.venv-tools/ -# Ignore IDE specific files +# Editors and OS files .idea/ .vscode/ - -# Ignore OS generated files .DS_Store Thumbs.db diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..89ca6bbf --- /dev/null +++ b/Makefile @@ -0,0 +1,40 @@ +ifeq ($(OS),Windows_NT) +ifdef MSYSTEM +FOUNDRY_BIN := $(HOME)/.foundry/bin +REPO_ROOT := $(shell pwd) +PATH_SEPARATOR := : +RM_RF := rm -rf out cache broadcast +else +FOUNDRY_BIN := $(USERPROFILE)/.foundry/bin +REPO_ROOT := $(CURDIR) +PATH_SEPARATOR := ; +RM_RF := powershell -NoProfile -ExecutionPolicy Bypass -Command "Remove-Item -Recurse -Force out,cache,broadcast -ErrorAction SilentlyContinue" +endif +VENV_BIN := .venv-tools/Scripts +else +FOUNDRY_BIN := $(HOME)/.foundry/bin +REPO_ROOT := $(CURDIR) +PATH_SEPARATOR := : +VENV_BIN := .venv-tools/bin +RM_RF := rm -rf out cache broadcast +endif +PATH := $(FOUNDRY_BIN)$(PATH_SEPARATOR)$(REPO_ROOT)/$(VENV_BIN)$(PATH_SEPARATOR)$(PATH) + +.PHONY: check build test fmt-check slither clean + +check: build test + +build: + forge build + +test: + forge test -vvv + +fmt-check: + forge fmt --check smart-contracts + +slither: + slither . --foundry-compile-all + +clean: + $(RM_RF) diff --git a/README.md b/README.md index 05741076..3c87c5c5 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,84 @@ # 6529Stream -6529 stream consists of a set of smart contracts (NextGen-modified contracts) to allow the minting/auctioning of drops +6529Stream is a set of Solidity smart contracts for 6529 NFT drops, including +fixed-price minting, auction flows, curator rewards, metadata generation, and +randomness adapters. -It has a TDH signer to act as an admin +## Status -## Process +This repository is pre-audit and not production-ready. -1. TDH holders provide rep to drops -2. If a Drop clears the hurdle for the network selected, it goes into a Pool -3. Once the Drops is within a Pool, addresses that meet the requirements of the TDH signer contract can sign a minting transaction -4. Once the TDH signer requirements are met anyone can mint the NFT to buy it or send it to an auction +The current CI and local smoke checks prove only that the contracts compile and +that the Foundry test command executes. They do not prove protocol correctness. +Known P0 blockers and the execution roadmap are tracked in +[`ops/ROADMAP.md`](ops/ROADMAP.md). + +## Drop Flow + +1. TDH holders provide reputation to drops. +2. If a drop clears the selected network hurdle, it enters a pool. +3. Once a drop is in a pool, addresses that meet TDH signer requirements can + sign a minting transaction. +4. Once signer requirements are met, the NFT can be minted through fixed-price + purchase or sent to auction. + +## Quickstart + +Install Foundry `v1.7.1`, then run: + +```bash +make check +``` + +The canonical smoke check runs: + +```bash +forge build +forge test -vvv +``` + +On Windows, install Python 3.8+ or the `py` launcher, then bootstrap and verify +with: + +```powershell +powershell -ExecutionPolicy Bypass -File scripts\bootstrap-windows.ps1 +powershell -ExecutionPolicy Bypass -File scripts\check.ps1 +``` + +On Linux or EC2, bootstrap and verify with: + +```bash +bash scripts/bootstrap-ec2.sh +make check +``` + +## Tooling + +Tool versions and non-gating diagnostic commands are documented in +[`docs/tooling.md`](docs/tooling.md). + +Current pinned versions: + +| Tool | Version | +| --- | --- | +| Foundry | `v1.7.1` | +| Solidity compiler | `0.8.19` | +| Slither | `0.11.5` | + +## Repository Layout + +| Path | Purpose | +| --- | --- | +| `smart-contracts/` | Solidity source | +| `test/` | Foundry tests | +| `script/` | Foundry scripts | +| `docs/` | Project, security, ADR, and operational docs | +| `ops/` | Roadmap and execution state | + +## Important Docs + +- [`ops/ROADMAP.md`](ops/ROADMAP.md) +- [`ops/AUTONOMOUS_RUN.md`](ops/AUTONOMOUS_RUN.md) +- [`docs/status.md`](docs/status.md) +- [`docs/known-blockers.md`](docs/known-blockers.md) +- [`docs/tooling.md`](docs/tooling.md) diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 00000000..22193baa --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,17 @@ +# Architecture Decision Records + +ADRs are required before unsafe P0 implementation work. + +Expected ADRs are tracked in `ops/ROADMAP.md`: + +- `0001-drop-authorization.md` +- `0002-auction-custody.md` +- `0003-payment-accounting.md` +- `0004-admin-governance.md` +- `0005-randomness.md` +- `0006-metadata-freeze.md` +- `0007-upgrade-redeployment.md` + +Each ADR should include problem, current behavior, intended behavior, +alternatives, security impact, migration impact, test plan, rollout plan, +non-goals, and accepted risks. diff --git a/docs/known-blockers.md b/docs/known-blockers.md new file mode 100644 index 00000000..3c82505d --- /dev/null +++ b/docs/known-blockers.md @@ -0,0 +1,15 @@ +# Known Blockers + +This file summarizes the high-level blockers from `ops/ROADMAP.md` for +contributors who start from the README. + +- Drop execution currently needs typed, replay-safe authorization. +- `tx.origin` usage must be removed from drop execution. +- Auction custody and settlement need an accepted state-machine model. +- Push payments must move to pull-payment accounting before production use. +- Randomizer request and callback validation need production hardening. +- Slither high/medium findings need triage before audit readiness. +- Meaningful unit, integration, regression, and invariant tests are missing. +- Deployment scripts, manifests, and rehearsal runbooks are missing. + +Do not treat the current build/test smoke baseline as a security claim. diff --git a/docs/status.md b/docs/status.md new file mode 100644 index 00000000..7a87a993 --- /dev/null +++ b/docs/status.md @@ -0,0 +1,15 @@ +# Project Status + +6529Stream is pre-audit and not production-ready. + +The current Gate A smoke baseline proves: + +- Foundry is configured to compile `smart-contracts`. +- `forge build` runs against Solidity `0.8.19`. +- `forge test -vvv` executes, even though meaningful tests are not yet present. +- CI can run the same build/test smoke commands and publish logs. + +The current baseline does not prove protocol correctness. Known blockers remain +tracked in `ops/ROADMAP.md`, including authorization, auction custody, +pull-payment accounting, randomizer hardening, static-analysis triage, and +meaningful tests. diff --git a/docs/tooling.md b/docs/tooling.md new file mode 100644 index 00000000..4f8fb802 --- /dev/null +++ b/docs/tooling.md @@ -0,0 +1,66 @@ +# Tooling + +6529Stream currently uses a pinned Foundry smoke baseline. + +## Versions + +| Tool | Version | +| --- | --- | +| Foundry | `v1.7.1` | +| Solidity compiler | `0.8.19` | +| Slither | `0.11.5` | +| solc-select | `1.2.0` | + +## Local Checks + +Run the canonical Gate A smoke check: + +```bash +make check +``` + +This runs: + +```bash +forge build +forge test -vvv +``` + +Windows contributors can run: + +```powershell +powershell -ExecutionPolicy Bypass -File scripts\check.ps1 +``` + +The Windows script prepends `%USERPROFILE%\.foundry\bin` to the current process +`PATH` so a fresh shell can find `forge` after bootstrap. + +## Bootstrap + +Linux or EC2: + +```bash +bash scripts/bootstrap-ec2.sh +``` + +Windows PowerShell: + +```powershell +powershell -ExecutionPolicy Bypass -File scripts\bootstrap-windows.ps1 +``` + +Windows bootstrap requires Python 3.8+ or the `py` launcher for the local +Slither and `solc-select` tool environment. Foundry itself is downloaded from +the pinned release asset and verified with SHA256 before extraction. + +## Non-Gating Diagnostics + +These commands are intentionally not part of `make check` yet: + +```bash +make fmt-check +make slither +``` + +Formatting and Slither have known baselines and should become gates only after +the roadmap items for formatting triage and Slither baseline acceptance land. diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 00000000..00e5a46a --- /dev/null +++ b/foundry.toml @@ -0,0 +1,17 @@ +[profile.default] +src = "smart-contracts" +test = "test" +script = "script" +out = "out" +cache_path = "cache" +libs = ["lib"] +solc_version = "0.8.19" +auto_detect_solc = false +evm_version = "paris" +optimizer = true +optimizer_runs = 200 + +[fmt] +line_length = 100 +tab_width = 4 +bracket_spacing = true diff --git a/ops/AUTONOMOUS_RUN.md b/ops/AUTONOMOUS_RUN.md index 569dcf31..0bc238a5 100644 --- a/ops/AUTONOMOUS_RUN.md +++ b/ops/AUTONOMOUS_RUN.md @@ -29,11 +29,11 @@ tests, security hardening, deployment discipline, and release/audit readiness. | Field | Value | | --- | --- | | Remote | `https://github.com/6529-Collections/6529Stream.git` | -| Active PR 1 branch | `codex/roadmap-control-plane` | -| Active PR 1 URL | `https://github.com/6529-Collections/6529Stream/pull/3` | +| Active PR branch | `codex/gate-a-reproducible-baseline` | +| Last merged PR | `https://github.com/6529-Collections/6529Stream/pull/3` | | Roadmap file | `ops/ROADMAP.md` | | State file | `ops/AUTONOMOUS_RUN.md` | -| Last updated | `2026-06-09 22:36 UTC` | +| Last updated | `2026-06-09 23:28 UTC` | ## Packaging Notes @@ -51,43 +51,63 @@ The queue will evolve as PRs merge and bot feedback arrives. | Order | Candidate PR | Gate | Scope | Status | | --- | --- | --- | --- | --- | -| 1 | Roadmap and autonomous run control plane | Gate A / planning | `ops/ROADMAP.md`, `ops/AUTONOMOUS_RUN.md` only unless PR packaging requires small docs metadata | In progress | -| 2 | Reproducible baseline tooling | Gate A | Foundry config, make/check command, bootstrap scripts, CI smoke workflow | Planned | +| 1 | Roadmap and autonomous run control plane | Gate A / planning | `ops/ROADMAP.md`, `ops/AUTONOMOUS_RUN.md` only unless PR packaging requires small docs metadata | Merged in PR #3 | +| 2 | Reproducible baseline tooling | Gate A | Foundry config, make/check command, bootstrap scripts, CI smoke workflow | Open in PR #4 | | 3 | Repo maturity and contributor docs | Gate A / Gate G foundation | README status, SECURITY, CONTRIBUTING, issue/PR templates, CODEOWNERS | Planned | | 4 | Characterization test skeleton | Gate A | Test directory, fixtures, compile-only or characterization scaffolding | Planned | | 5 | Slither baseline appendix/config | Gate A / Gate C foundation | Static analysis command/config and tracked baseline issue rows | Planned | ## Current PR Worklog -### PR 1: Roadmap and autonomous run control plane +### PR #4: Reproducible baseline tooling (Queue Item 2) -Status: In progress. -Branch: `codex/roadmap-control-plane`. -Pull request: `https://github.com/6529-Collections/6529Stream/pull/3`. +Status: Merge-ready; CI is green, CodeRabbit is green, and all visible review threads are +resolved. +Branch: `codex/gate-a-reproducible-baseline`. +Pull request: `https://github.com/6529-Collections/6529Stream/pull/4`. Goal: -- Make the roadmap canonical, gated, issue-ready, and traceable. -- Add durable autonomous run state to support long-running execution. +- Make a fresh checkout compile real Solidity sources instead of compiling + nothing. +- Add a canonical `make check` smoke gate. +- Add Linux and Windows bootstrap/check scripts. +- Add CI build/test smoke with uploaded logs. +- Add minimal setup/status docs and repository skeleton directories. Candidate files: -- `ops/ROADMAP.md` - `ops/AUTONOMOUS_RUN.md` +- `.editorconfig` +- `.gitattributes` +- `.gitignore` +- `.github/workflows/ci.yml` +- `foundry.toml` +- `Makefile` +- `requirements-tools.txt` +- `scripts/` +- `docs/` +- `test/README.md` +- `script/README.md` +- `README.md` +- Compile-surface interface import fixes if required for honest `forge build` Validation: -- `rg -n "^#|^##|^###" ops/ROADMAP.md` -- `rg -n "^#|^##|^###" ops/AUTONOMOUS_RUN.md` -- Confirm Markdown code fences are balanced. -- Confirm no unrelated files are staged in the PR. +- `forge build` passed. +- `forge test -vvv` passed command execution and reported no tests found. +- `make check` passed. +- `powershell -ExecutionPolicy Bypass -File scripts\check.ps1` passed. +- `git check-ignore -v out/ cache/ broadcast/ .venv-tools/ .env.local` confirmed generated/local artifacts are ignored. +- Claude fix pass validation: `bash -n scripts/bootstrap-ec2.sh`, `bash -n scripts/check.sh`, PowerShell parser check for `scripts\bootstrap-windows.ps1`, `make -n slither`, and env-template ignore checks passed. +- CodeRabbit CI hardening validation: GitHub Actions references are pinned to 40-character SHAs, `actions/checkout` uses `persist-credentials: false`, `git diff --check` passed, `make check` passed, and `powershell -ExecutionPolicy Bypass -File scripts\check.ps1` passed. +- Remote validation: GitHub Actions CI passed on `8944025167a65e120f8e46899d65e3f9cfbbd150`, CodeRabbit reported no actionable comments on the latest pass, and all visible review threads were resolved. Next steps: -1. Finish local verification of roadmap/state files. -2. Monitor CI and bot comments. -3. Resolve any actionable review. -4. Merge when clean. +1. Merge PR #4. +2. Refresh a clean branch from `origin/main`. +3. Start Queue Item 3: CI/review hardening follow-up. ## Decision Log @@ -98,6 +118,14 @@ Next steps: | 2026-06-09 22:34 | Start with a docs/state PR | It establishes the control plane before code changes and is low risk | | 2026-06-09 22:34 | Create PR 1 from a clean branch based on `origin/main` | The initial checkout contained unrelated dirty files and was on the already-merged PR #2 branch | | 2026-06-09 22:36 | Open PR #3 for roadmap/control-plane work | PR contains only `ops/ROADMAP.md` and `ops/AUTONOMOUS_RUN.md` | +| 2026-06-09 22:49 | Merge PR #3 | CodeRabbit was green and review threads were resolved | +| 2026-06-09 22:55 | Start Gate A reproducible-baseline PR | Fresh Foundry config exposed that the prior build baseline compiled nothing | +| 2026-06-09 22:55 | Allow compile-surface import fixes in PR 2 | Honest `forge build` requires the randomizer contracts to import existing Stream interfaces | +| 2026-06-09 23:00 | Local validation passed for PR 2 | `make check` and Windows `scripts/check.ps1` pass; generated Foundry artifacts are ignored | +| 2026-06-09 23:02 | Open PR #4 | Explicit Claude review requested because bot review may not run automatically | +| 2026-06-09 23:18 | Implement Claude PR #4 review fixes | Harden Windows/Linux bootstrap, Makefile PATH handling, bash missing-tool UX, and env template ignores | +| 2026-06-09 23:23 | Implement CodeRabbit PR #4 review fixes | Pin CI actions to commit SHAs, disable persisted checkout credentials, and clarify the PR worklog label | +| 2026-06-09 23:28 | Mark PR #4 merge-ready | CI passed, CodeRabbit latest pass had no actionable comments, and visible review threads are resolved | ## Resume Instructions diff --git a/requirements-tools.txt b/requirements-tools.txt new file mode 100644 index 00000000..c3c6ad13 --- /dev/null +++ b/requirements-tools.txt @@ -0,0 +1,2 @@ +slither-analyzer==0.11.5 +solc-select==1.2.0 diff --git a/script/README.md b/script/README.md new file mode 100644 index 00000000..3e1f1572 --- /dev/null +++ b/script/README.md @@ -0,0 +1,7 @@ +# Deployment Scripts + +Foundry deployment and rehearsal scripts belong in this directory. + +Deployment scripts are not implemented yet. Gate E in `ops/ROADMAP.md` defines +the expected deployment rehearsal, manifest, verification, and post-deploy +checklist requirements. diff --git a/scripts/bootstrap-ec2.sh b/scripts/bootstrap-ec2.sh new file mode 100644 index 00000000..4805f26e --- /dev/null +++ b/scripts/bootstrap-ec2.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +set -euo pipefail + +FOUNDRY_VERSION="${FOUNDRY_VERSION:-v1.7.1}" + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$repo_root" + +install_packages() { + if command -v apt-get >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y git curl tar build-essential make python3 python3-pip python3-venv ca-certificates + elif command -v dnf >/dev/null 2>&1; then + sudo dnf install -y git curl tar gcc gcc-c++ make python3 python3-pip ca-certificates + elif command -v yum >/dev/null 2>&1; then + sudo yum install -y git curl tar gcc gcc-c++ make python3 python3-pip ca-certificates + else + echo "Unsupported package manager. Install git, curl, tar, make, gcc, python3, pip, venv, and ca-certificates manually." + exit 1 + fi +} + +foundry_arch() { + case "$(uname -m)" in + x86_64|amd64) + echo "amd64" + ;; + aarch64|arm64) + echo "arm64" + ;; + *) + echo "Unsupported architecture for Foundry release assets: $(uname -m)" >&2 + exit 1 + ;; + esac +} + +install_foundry() { + local arch + local asset_name + local checksum_name + local release_base + local temp_dir + local archive_path + local checksum_path + local expected_hash + local actual_hash + + export PATH="$HOME/.foundry/bin:$PATH" + arch="$(foundry_arch)" + asset_name="foundry_${FOUNDRY_VERSION}_linux_${arch}.tar.gz" + checksum_name="foundry_${FOUNDRY_VERSION}_linux_${arch}.sha256" + release_base="https://github.com/foundry-rs/foundry/releases/download/${FOUNDRY_VERSION}" + temp_dir="$(mktemp -d)" + archive_path="${temp_dir}/${asset_name}" + checksum_path="${temp_dir}/${checksum_name}" + + mkdir -p "$HOME/.foundry/bin" + curl -fsSL "${release_base}/${asset_name}" -o "$archive_path" + curl -fsSL "${release_base}/${checksum_name}" -o "$checksum_path" + + expected_hash="$(awk '{print $1}' "$checksum_path")" + actual_hash="$(sha256sum "$archive_path" | awk '{print $1}')" + if [ "$expected_hash" != "$actual_hash" ]; then + echo "SHA256 mismatch for ${asset_name}. Expected ${expected_hash}, got ${actual_hash}." >&2 + exit 1 + fi + + tar -xzf "$archive_path" -C "$HOME/.foundry/bin" + forge --version +} + +install_python_tools() { + python3 -m venv .venv-tools + # shellcheck source=/dev/null + source .venv-tools/bin/activate + python -m pip install --upgrade pip + python -m pip install -r requirements-tools.txt + solc-select install 0.8.19 + solc-select use 0.8.19 +} + +install_packages +install_foundry +install_python_tools + +cat <<'EOF' + +Bootstrap complete. + +For this shell, run: + source .venv-tools/bin/activate + export PATH="$HOME/.foundry/bin:$PATH" + +Then verify: + make check + +Non-gating diagnostics for later roadmap items: + make fmt-check + make slither + +EOF diff --git a/scripts/bootstrap-windows.ps1 b/scripts/bootstrap-windows.ps1 new file mode 100644 index 00000000..3753e394 --- /dev/null +++ b/scripts/bootstrap-windows.ps1 @@ -0,0 +1,109 @@ +#Requires -Version 5.1 +[CmdletBinding()] +param( + [string]$Version = $(if ($env:FOUNDRY_VERSION) { $env:FOUNDRY_VERSION } else { "v1.7.1" }), + [string]$InstallDir = $(Join-Path $HOME ".foundry\bin"), + [switch]$SkipPathUpdate +) + +$ErrorActionPreference = "Stop" + +if (-not $Version.StartsWith("v")) { + $Version = "v$Version" +} + +$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..") +$assetName = "foundry_${Version}_win32_amd64.zip" +$checksumName = "foundry_${Version}_win32_amd64.sha256" +$releaseBase = "https://github.com/foundry-rs/foundry/releases/download/$Version" +$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) "6529stream-foundry-$Version" +$archivePath = Join-Path $tempDir $assetName +$checksumPath = Join-Path $tempDir $checksumName + +function Invoke-Native { + param( + [Parameter(Mandatory = $true)] + [string]$FilePath, + [string[]]$Arguments = @() + ) + + & $FilePath @Arguments + if ($LASTEXITCODE -ne 0) { + throw "$FilePath failed with exit code $LASTEXITCODE." + } +} + +function Resolve-Python { + $pythonCommand = Get-Command python -CommandType Application -ErrorAction SilentlyContinue | + Where-Object { $_.Source -notmatch "\\WindowsApps\\" } | + Select-Object -First 1 + + if ($pythonCommand) { + return @{ + FilePath = $pythonCommand.Source + Arguments = @() + } + } + + $pyLauncher = Get-Command py -CommandType Application -ErrorAction SilentlyContinue | + Select-Object -First 1 + if ($pyLauncher) { + return @{ + FilePath = $pyLauncher.Source + Arguments = @("-3") + } + } + + throw "Python 3.8+ is required. Install Python from python.org or install the py launcher, then re-run this script." +} + +New-Item -ItemType Directory -Force $tempDir | Out-Null +New-Item -ItemType Directory -Force $InstallDir | Out-Null + +Write-Host "Downloading Foundry $Version..." +Invoke-WebRequest -UseBasicParsing -Uri "$releaseBase/$assetName" -OutFile $archivePath +Invoke-WebRequest -UseBasicParsing -Uri "$releaseBase/$checksumName" -OutFile $checksumPath + +$expectedHash = ((Get-Content $checksumPath | Select-Object -First 1) -split "\s+")[0].Trim().ToLowerInvariant() +$actualHash = (Get-FileHash $archivePath -Algorithm SHA256).Hash.ToLowerInvariant() +if ($expectedHash -ne $actualHash) { + throw "SHA256 mismatch for $assetName. Expected $expectedHash, got $actualHash." +} + +Expand-Archive -Force $archivePath $InstallDir + +if (-not $SkipPathUpdate) { + $userPath = [Environment]::GetEnvironmentVariable("Path", "User") + $pathParts = @() + if ($userPath) { + $pathParts = $userPath -split ";" | Where-Object { $_ -ne "" } + } + + $normalizedInstallDir = $InstallDir.TrimEnd("\") + $alreadyPresent = $pathParts | Where-Object { $_.TrimEnd("\") -ieq $normalizedInstallDir } + if (-not $alreadyPresent) { + [Environment]::SetEnvironmentVariable("Path", (($pathParts + $InstallDir) -join ";"), "User") + Write-Host "Added $InstallDir to the user PATH. Open a new terminal to use it automatically." + } +} + +$env:Path = "$InstallDir;$env:Path" +Invoke-Native -FilePath (Join-Path $InstallDir "forge.exe") -Arguments @("--version") + +Set-Location $repoRoot +$python = Resolve-Python +Invoke-Native -FilePath $python.FilePath -Arguments ($python.Arguments + @("-m", "venv", ".venv-tools")) +$toolPython = Join-Path $repoRoot ".venv-tools\Scripts\python.exe" +if (-not (Test-Path $toolPython)) { + throw "Python virtual environment was not created at $toolPython." +} +Invoke-Native -FilePath $toolPython -Arguments @("-m", "pip", "install", "--upgrade", "pip") +Invoke-Native -FilePath $toolPython -Arguments @("-m", "pip", "install", "-r", "requirements-tools.txt") +Invoke-Native -FilePath (Join-Path $repoRoot ".venv-tools\Scripts\solc-select.exe") -Arguments @("install", "0.8.19") +Invoke-Native -FilePath (Join-Path $repoRoot ".venv-tools\Scripts\solc-select.exe") -Arguments @("use", "0.8.19") + +Write-Host "" +Write-Host "Bootstrap complete. This shell can now run:" +Write-Host " forge build" +Write-Host " forge test -vvv" +Write-Host " powershell -ExecutionPolicy Bypass -File scripts\check.ps1" diff --git a/scripts/check.ps1 b/scripts/check.ps1 new file mode 100644 index 00000000..a0345cce --- /dev/null +++ b/scripts/check.ps1 @@ -0,0 +1,20 @@ +#Requires -Version 5.1 +[CmdletBinding()] +param() + +$ErrorActionPreference = "Stop" + +$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..") +Set-Location $repoRoot + +$foundryBin = Join-Path $HOME ".foundry\bin" +if (Test-Path $foundryBin) { + $env:Path = "$foundryBin;$env:Path" +} + +if (-not (Get-Command forge -ErrorAction SilentlyContinue)) { + throw "forge was not found. Run scripts\bootstrap-windows.ps1, then retry this command." +} + +forge build +forge test -vvv diff --git a/scripts/check.sh b/scripts/check.sh new file mode 100644 index 00000000..d2cd9646 --- /dev/null +++ b/scripts/check.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$repo_root" + +export PATH="$HOME/.foundry/bin:$PATH" + +if ! command -v forge >/dev/null 2>&1; then + echo "forge was not found. Run bash scripts/bootstrap-ec2.sh, then retry this command." >&2 + exit 1 +fi + +forge build +forge test -vvv diff --git a/smart-contracts/RandomizerRNG.sol b/smart-contracts/RandomizerRNG.sol index 667f51c9..2274d1fb 100644 --- a/smart-contracts/RandomizerRNG.sol +++ b/smart-contracts/RandomizerRNG.sol @@ -11,15 +11,15 @@ pragma solidity ^0.8.19; import "./ArrngConsumer.sol"; -import "./INextGenCore.sol"; -import "./INextGenAdmins.sol"; +import "./IStreamCore.sol"; +import "./IStreamAdmins.sol"; contract NextGenRandomizerRNG is ArrngConsumer { mapping(uint256 => uint256) public requestToToken; address gencore; - INextGenCore public gencoreContract; - INextGenAdmins private adminsContract; + IStreamCore public gencoreContract; + IStreamAdmins private adminsContract; event Withdraw(address indexed _add, bool status, uint256 indexed funds); uint256 ethRequired; mapping(uint256 => uint256) public tokenToRequest; @@ -27,8 +27,8 @@ contract NextGenRandomizerRNG is ArrngConsumer { constructor(address _gencore, address _adminsContract, address _arRNG) ArrngConsumer(_arRNG) { gencore = _gencore; - gencoreContract = INextGenCore(_gencore); - adminsContract = INextGenAdmins(_adminsContract); + gencoreContract = IStreamCore(_gencore); + adminsContract = IStreamAdmins(_adminsContract); } modifier FunctionAdminRequired(bytes4 _selector) { @@ -58,13 +58,13 @@ contract NextGenRandomizerRNG is ArrngConsumer { // function to update contracts function updateAdminContract(address _newadminsContract) public FunctionAdminRequired(this.updateAdminContract.selector) { - require(INextGenAdmins(_newadminsContract).isAdminContract() == true, "Contract is not Admin"); - adminsContract = INextGenAdmins(_newadminsContract); + require(IStreamAdmins(_newadminsContract).isAdminContract() == true, "Contract is not Admin"); + adminsContract = IStreamAdmins(_newadminsContract); } function updateCoreContract(address _gencore) public FunctionAdminRequired(this.updateCoreContract.selector) { gencore = _gencore; - gencoreContract = INextGenCore(_gencore); + gencoreContract = IStreamCore(_gencore); } // function to update cost @@ -89,4 +89,4 @@ contract NextGenRandomizerRNG is ArrngConsumer { function isRandomizerContract() external view returns (bool) { return true; } -} \ No newline at end of file +} diff --git a/smart-contracts/RandomizerVRF.sol b/smart-contracts/RandomizerVRF.sol index e8f1c28a..88dab81a 100644 --- a/smart-contracts/RandomizerVRF.sol +++ b/smart-contracts/RandomizerVRF.sol @@ -12,8 +12,8 @@ pragma solidity ^0.8.19; import "./VRFCoordinatorV2Interface.sol"; import "./VRFConsumerBaseV2.sol"; -import "./INextGenCore.sol"; -import "./INextGenAdmins.sol"; +import "./IStreamCore.sol"; +import "./IStreamAdmins.sol"; contract NextGenRandomizerVRF is VRFConsumerBaseV2 { event RequestFulfilled(uint256 requestId, uint256[] randomWords); @@ -32,15 +32,15 @@ contract NextGenRandomizerVRF is VRFConsumerBaseV2 { mapping(uint256 => uint256) public requestToToken; address gencore; - INextGenCore public gencoreContract; - INextGenAdmins private adminsContract; + IStreamCore public gencoreContract; + IStreamAdmins private adminsContract; constructor(uint64 subscriptionId, address vrfCoordinator, address _gencore, address _adminsContract) VRFConsumerBaseV2(vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); s_subscriptionId = subscriptionId; gencore = _gencore; - gencoreContract = INextGenCore(_gencore); - adminsContract = INextGenAdmins(_adminsContract); + gencoreContract = IStreamCore(_gencore); + adminsContract = IStreamAdmins(_adminsContract); } modifier FunctionAdminRequired(bytes4 _selector) { @@ -91,13 +91,13 @@ contract NextGenRandomizerVRF is VRFConsumerBaseV2 { // function to update contracts function updateAdminContract(address _newadminsContract) public FunctionAdminRequired(this.updateAdminContract.selector) { - require(INextGenAdmins(_newadminsContract).isAdminContract() == true, "Contract is not Admin"); - adminsContract = INextGenAdmins(_newadminsContract); + require(IStreamAdmins(_newadminsContract).isAdminContract() == true, "Contract is not Admin"); + adminsContract = IStreamAdmins(_newadminsContract); } function updateCoreContract(address _gencore) public FunctionAdminRequired(this.updateCoreContract.selector) { gencore = _gencore; - gencoreContract = INextGenCore(_gencore); + gencoreContract = IStreamCore(_gencore); } // get randomizer contract status @@ -105,4 +105,4 @@ contract NextGenRandomizerVRF is VRFConsumerBaseV2 { return true; } -} \ No newline at end of file +} diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000..101721be --- /dev/null +++ b/test/README.md @@ -0,0 +1,7 @@ +# Tests + +Foundry tests belong in this directory. + +The current Gate A smoke baseline intentionally has no meaningful tests yet. +The next test work should add characterization fixtures before changing P0 +protocol behavior, as described in `ops/ROADMAP.md`.