diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..773f8f1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,36 @@ +--- +name: Bug Report +about: Report a bug or unexpected behavior +title: "[BUG] " +labels: bug +assignees: "" +--- + +## Description + +A clear description of the bug. + +## Steps to Reproduce + +1. ... +2. ... +3. ... + +## Expected Behavior + +What you expected to happen. + +## Actual Behavior + +What actually happened. + +## Environment + +- Foundry version (`forge --version`): +- Solidity version: +- OS: +- Network (if applicable): + +## Additional Context + +Any other context, screenshots, or log output. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..34e9d07 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,35 @@ +--- +name: Feature Request / Task +about: Propose a new feature or describe a task from a spec +title: "[FEAT] " +labels: enhancement +assignees: "" +--- + +## Summary + +Brief description of the feature or task. + +## Motivation + +Why is this needed? Link to the relevant spec or discussion if applicable. + +## Specification + +### Requirements + +- [ ] Requirement 1 +- [ ] Requirement 2 + +### Acceptance Criteria + +- [ ] Criterion 1 +- [ ] Criterion 2 + +## Design Considerations + +Describe any architectural decisions, trade-offs, or security considerations. + +## Dependencies + +List any external dependencies, upstream changes, or blocking tasks. diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 0000000..5d5f0fd --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,129 @@ +name: Claude Code Assistant (Solidity) + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + pull_request_review: + types: [submitted] + issues: + types: [opened, assigned] + pull_request: + types: [opened, synchronize] + +jobs: + # ─── 1. Claude Code Assistant (triggered by @claude mentions) ───────────── + claude-assistant: + name: Claude Code + runs-on: ubuntu-latest + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + permissions: + contents: write + pull-requests: write + issues: write + id-token: write + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 1 + + # Make Foundry & Solhint available to Claude so it can run them + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Install Solhint + run: npm install -g solhint + + - name: Run Claude Code + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + claude_args: | + --max-turns 15 + --allowedTools "Bash(forge build),Bash(forge test*),Bash(forge fmt*),Bash(forge coverage*),Bash(forge snapshot*),Bash(solhint*),Read,Edit,Write,Glob,Grep" + --system-prompt "You are an expert Solidity and EVM smart contract engineer. + + CONTEXT: + - This repo uses Foundry (forge, cast, anvil). Tests are in test/, contracts in src/, scripts in script/. + - Dependencies are managed as git submodules in lib/. + - Always check forge build and forge test pass before suggesting changes. + - Solidity version: check foundry.toml or pragma statements before assuming. + + SECURITY RULES (non-negotiable): + - Never suggest patterns that bypass checks-effects-interactions. + - Flag any reentrancy, integer overflow, access control, or oracle manipulation risks. + - Prefer OpenZeppelin battle-tested libraries over custom implementations. + - Never suggest storing private keys or secrets in contract state or scripts. + - When reviewing upgradeable contracts, always check storage layout collisions. + + CODE QUALITY: + - Write Solidity tests (not just JS/TS) using forge-std. + - Include fuzz tests (vm.assume, bound()) for numeric inputs. + - Add NatSpec comments (@notice, @param, @return) on all public functions. + - Report gas impact of suggested changes using forge snapshot. + - Follow the Checks-Effects-Interactions pattern strictly. + + GAS OPTIMISATION: + - Suggest packing storage slots where safe to do so. + - Prefer custom errors over revert strings. + - Use immutable and constant where appropriate. + - Flag unnecessary SLOADs in loops." + + # ─── 3. Automated security review on every PR ───────────────────────────── + claude-security-review: + name: Claude Security Review + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && github.event.action == 'opened' + permissions: + contents: read + pull-requests: write + issues: write + id-token: write + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 2 + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Automated Claude Security Review + uses: anthropics/claude-code-action@v1 + with: + anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + prompt: | + REPO: ${{ github.repository }} + PR NUMBER: ${{ github.event.pull_request.number }} + BRANCH: ${{ github.head_ref }} + + Perform a focused Solidity security and gas review of the changes in this PR. + Use `git diff HEAD~1` to see what changed. + + Structure your review as: + + ## 🔴 Critical / High (block merge) + Reentrancy, access control bypasses, integer issues, fund loss vectors. + + ## 🟡 Medium (should fix) + Logic bugs, incorrect event emissions, missing input validation. + + ## 🟢 Low / Informational + Gas optimisations, NatSpec gaps, style issues. + + ## ✅ Gas Report Delta + Run `forge snapshot --diff` if applicable and summarise changes. + + If there are no issues in a category, write "None found." + Be concise and actionable. Cite the file and line number for each finding. + claude_args: | + --max-turns 10 + --allowedTools "Bash(forge build),Bash(forge test*),Bash(forge snapshot*),Bash(git diff*),Read,Glob,Grep" diff --git a/.github/workflows/slither.yaml b/.github/workflows/slither.yaml new file mode 100644 index 0000000..10e68ba --- /dev/null +++ b/.github/workflows/slither.yaml @@ -0,0 +1,30 @@ +name: Slither Analysis + +on: + pull_request: + branches: [main, master, staging, dev, "feat/**", "fix/**"] + +jobs: + analyze: + name: Slither + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Run Slither + uses: crytic/slither-action@v0.4.0 + id: slither + with: + fail-on: none + sarif: results.sarif + slither-config: slither.config.json + + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 42c3cda..d7d6509 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,36 +1,59 @@ name: test +permissions: + contents: read + on: pull_request: - branches: [main, master, staging, dev, feat/**, fix/**] + branches: [main, master, staging, dev, "feat/**", "fix/**"] env: FOUNDRY_PROFILE: ci jobs: - check: - strategy: - fail-fast: true + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Show Forge version + run: forge --version + + - name: Build and check contract sizes + run: forge build --sizes - name: Foundry project + test: + name: Test runs-on: ubuntu-latest + needs: build steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 + + - name: Run tests + run: forge test -vvv + + coverage: + name: Coverage + runs-on: ubuntu-latest + needs: build + steps: + - uses: actions/checkout@v4 with: - version: nightly - - - name: Run Forge build - run: | - forge --version - forge build --sizes - id: build - - - name: Run Forge tests - run: | - forge test -vvv - id: test + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Generate coverage report + run: forge coverage diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ca96380..2290e51 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,7 @@ - [Dev](#dev) - [Feature](#feature) - [Fix](#fix) +- [Repository Setup](#repository-setup) - [Code Practices](#code-practices) - [Code Style](#code-style) - [Interfaces](#interfaces) @@ -18,6 +19,7 @@ - [Deployment](#deployment) - [Deployer Template](#deployer-template-1) - [Deployment](#deployment-1) + - [Deployment Safety](#deployment-safety) - [Deployment Info Generation](#deployment-info-generation) - [Deployer Template Script](#deployer-template-script) - [Releases](#releases) @@ -65,6 +67,35 @@ Any new feature should be developed on a separate branch. The naming convention Any bug fixes should be developed on a separate branch. The naming convention for these branches is `fix/*`. Once the fix is complete, a pull request into the dev branch can be created. +## Repository Setup + +When creating a new repository from this template, configure the following branch protection rules to enforce the branching strategy described above. + +### Main Branch Protection + +- Require pull request before merging + - Required approvals: 2 (at minimum) + - Require review from Code Owners (ensures security team review via CODEOWNERS) + - Dismiss stale reviews when new commits are pushed +- Require status checks to pass before merging + - Required checks: `Build`, `Test`, `Coverage`, `Slither`, `pre-commit` +- Require branches to be up to date before merging +- Do not allow bypassing the above settings + +### Staging Branch Protection + +- Require pull request before merging + - Required approvals: 1 +- Require status checks to pass before merging + - Required checks: `Build`, `Test`, `Coverage`, `Slither`, `pre-commit` + +### Dev Branch Protection + +- Require pull request before merging + - Required approvals: 1 +- Require status checks to pass before merging + - Required checks: `Build`, `Test`, `pre-commit` + ## Code Practices ### Code Style @@ -148,21 +179,48 @@ This repo provides a deployer template library for consistency between scripts a This repo set up the following RPCs in the `foundry.toml` file: - mainnet: Ethereum Mainnet -- goerli: Ethereum Goerli - sepolia: Ethereum Sepolia - polygon_pos: Polygon PoS -- mumbai: Polygon Mumbai -- polygon_zkevm: Polygon zkEVM -- polygon_zkevm_testnet: Polygon zkEVM Testnet +- amoy: Polygon Amoy To deploy the contracts, provide the `--broadcast` flag to the forge script command. Should the etherscan verification time out, it can be picked up again by replacing the `--broadcast` flag with `--resume`. -Deploy the contracts to one of the predefined networks by providing the according key with the `--rpc-url` flag. Most of the predefined networks require the `INFURA_KEY` environment variable to be set in the `.env` file. +Deploy the contracts to one of the predefined networks by providing the according key with the `--rpc-url` flag. Most of the predefined networks require the `ALCHEMY_KEY` environment variable to be set in the `.env` file. Including the `--verify` flag will verify deployed contracts on Etherscan. Define the appropriate environment variable for the Etherscan api key in the `.env` file. ```shell -forge script script/Deploy.s.sol --broadcast --rpc-url --verify +forge script script/Deploy.s.sol --broadcast --rpc-url --slow --verify ``` +### Deployment Safety + +Follow these steps for safe deployments: + +1. **Simulate first.** Always run the deployment script without `--broadcast` to verify the transaction sequence: + ```shell + forge script script/Deploy.s.sol --rpc-url + ``` + +2. **Review the simulation output.** Check the simulated transactions in the `broadcast/` directory. Verify: + - Correct contract addresses and constructor arguments + - Expected number of transactions + - Gas estimates are reasonable + +3. **Deploy with `--slow`.** When broadcasting, use the `--slow` flag to wait for each transaction to be confirmed before sending the next: + ```shell + forge script script/Deploy.s.sol --broadcast --rpc-url --slow --verify + ``` + +4. **Handle verification timeouts.** If Etherscan verification times out, resume it without redeploying: + ```shell + forge script script/Deploy.s.sol --resume --rpc-url --verify + ``` + +5. **Post-deployment.** After successful deployment: + - Generate deployment log files + - Transfer ownership if applicable + - Complete upgrade process if applicable + - Update the PR checklist items in the pull request template + ## Releases Releases should be created whenever the code on the main branch is updated to reflect a deployment or an upgrade on a network. The release should be named after the version of the contracts deployed or upgraded. diff --git a/README.md b/README.md index c87e19b..e312d9d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ This template repo is a quick and easy way to get started with a new Solidity pr Follow these steps to set up your local environment: - [Install foundry](https://book.getfoundry.sh/getting-started/installation) -- Install dependencies: `forge solodeer install` +- Install dependencies: `forge soldeer install` - Build contracts: `forge build` - Test contracts: `forge test` @@ -31,12 +31,18 @@ If you intend to develop on this repo, follow the steps outlined in [CONTRIBUTIN This repo utilizes versioned deployments. For more information on how to use forge scripts within the repo, check [here](CONTRIBUTING.md#deployment). -Smart contracts are deployed or upgraded using the following command: +Smart contracts are deployed using a simulation-first approach: ```shell -forge script script/Deploy.s.sol --broadcast --rpc-url --verify +# 1. Simulate the deployment (no broadcast) +forge script script/Deploy.s.sol --rpc-url + +# 2. Deploy with transaction confirmation and verification +forge script script/Deploy.s.sol --broadcast --rpc-url --slow --verify ``` +For detailed deployment safety guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md#deployment-safety). + ## Docs The documentation and architecture diagrams for the contracts within this repo can be found [here](docs/). diff --git a/slither.config.json b/slither.config.json index e0d7e2a..3583960 100644 --- a/slither.config.json +++ b/slither.config.json @@ -1,3 +1,3 @@ { - "filter_paths": "(lib/|test/|scripts/)" + "filter_paths": "(lib/|test/|script/)" }