A comprehensive, reproducible development environment for the Diamonds Ethereum smart contract project using ERC-2535 Diamond Proxy Standard.
- Docker: Version 20.10+ with Docker Compose
- VS Code: Version 1.70+ with Dev Containers extension
- Git: Version 2.30+
-
Clone the repository:
git clone https://github.com/<git-org-name>/<git-repo-name>.git cd <git-repo-name>
-
Open in VS Code:
code . -
Reopen in DevContainer:
- When prompted, click "Reopen in Container"
- Or use Command Palette:
Dev Containers: Reopen in Container
-
Initial setup (runs automatically):
- Dependencies installation
- TypeScript/Solidity compilation
- Security tools configuration
- TypeChain types generation
- Node.js 20 with Yarn 4.x
- TypeScript with strict configuration
- Solidity ^0.8.19 with Hardhat
- ERC-2535 Diamond Proxy architecture
- Hardhat - Ethereum development framework
- TypeChain - Type-safe contract interactions
- Diamond Proxy Tools - ERC-2535 utilities
- Multi-chain Testing - Cross-network fork testing
- Semgrep - Code security scanning
- Slither - Solidity smart contract analysis
- Snyk - Dependency vulnerability scanning
- Socket.dev - Supply chain security
- OSV-Scanner - Known vulnerability database
- git-secrets - Secret detection and prevention
- Solidity support (JuanBlanco.solidity, NomicFoundation.hardhat-solidity)
- TypeScript/JavaScript (ms-vscode.vscode-typescript-next)
- ESLint/Prettier integration
- Git/GitHub integration
- Docker support
- Security tools
# Install dependencies
yarn install
# Compile contracts and generate types
yarn compile
# Run test suite
yarn test
# Run security scans
yarn security-check
# Start local blockchain
npx hardhat node
# Deploy to local network
npx hardhat run scripts/deploy/local.ts# Run all security tools
yarn security-check
# Individual security scans
yarn audit # Dependency audit
yarn semgrep:scan # Code security
yarn slither:scan # Contract analysis
yarn snyk:test # Vulnerability scan
# Code quality
yarn lint # ESLint
yarn format # Prettier# Generate diamond ABI and types
npx hardhat diamond:generate-abi-typechain --diamond-name <DIAMOND_NAME>
# Deploy diamond
npx hardhat run scripts/deploy/diamond.ts
# Add facet to diamond
npx hardhat run scripts/facets/addFacet.ts
# Upgrade diamond
npx hardhat run scripts/upgrade/diamond.ts# Test on multiple networks
yarn test:multichain --chains hardhat,sepolia,polygon
# Fork mainnet for testing
npx hardhat node --fork https://mainnet.infura.io/v3/YOUR_KEY
# Test specific network
npx hardhat test --network sepoliaCopy .devcontainer/.env.example to .env and configure:
# Network RPC URLs
MAINNET_RPC_URL=https://mainnet.infura.io/v3/YOUR_KEY
SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_KEY
# API Keys
INFURA_PROJECT_ID=your_infura_project_id
ETHERSCAN_API_KEY=your_etherscan_key
SNYK_TOKEN=your_snyk_token
# Development settings
NODE_ENV=development
HARDHAT_NETWORK=hardhatThe DevContainer includes optimized settings for:
- Solidity development with proper compiler version
- TypeScript with strict type checking
- ESLint/Prettier integration
- Git integration with security hooks
- File associations for blockchain files
Use Docker Compose for additional services:
# Start with local Hardhat node
docker-compose up devcontainer hardhat-node
# Start with full stack (database, IPFS, etc.)
docker-compose --profile database --profile ipfs up
# Start with Ganache instead of Hardhat
docker-compose --profile ganache up- devcontainer: Main development environment
- hardhat-node: Local Hardhat blockchain network
- ganache-node: Alternative local blockchain (profile: ganache)
- ipfs-node: IPFS decentralized storage (profile: ipfs)
- postgres-db: PostgreSQL database (profile: database)
- redis-cache: Redis caching (profile: cache)
- graph-node: The Graph indexing (profile: graph)
Automatically prevents committing sensitive data:
# Scan repository for secrets
git secrets --scan
# Add custom patterns
git secrets --add 'PRIVATE_KEY\s*=\s*["'\'']*0x[a-fA-F0-9]{64}["'\'']*'# Run complete security audit
yarn security-check
# Results include:
# - Dependency vulnerabilities (Snyk)
# - Code security issues (Semgrep)
# - Contract vulnerabilities (Slither)
# - Supply chain risks (Socket.dev)
# - Known vulnerabilities (OSV-Scanner)OAuth flow doesn't work in devcontainers. Use token-based authentication:
# Option 1: Direct authentication with token
# Get your token from: https://app.snyk.io/account
snyk auth <your-token>
# Option 2: Environment variable (recommended for persistence)
export SNYK_TOKEN=<your-token>
# Add to .env file for automatic loading
echo "SNYK_TOKEN=your_snyk_token" >> .env
# Verify authentication
snyk whoamiexport SOCKET_CLI_API_TOKEN=your_tokenThe DevContainer environment exactly matches GitHub Actions CI/CD:
# Validate environment parity
.devcontainer/scripts/github-actions-setup.sh
# Run CI simulation
yarn install --frozen-lockfile
yarn build
yarn test
yarn security-check- Identical Node.js/Yarn versions
- Same security tool versions
- Matching cache directories
- Production-like settings
- Frozen lockfile installations
# Check Docker resources
docker system info
# Clean up and rebuild
docker system prune -a
docker volume prune# Clear caches
rm -rf node_modules .yarn/cache
yarn cache clean
# Reinstall
yarn install --frozen-lockfile# Clean and recompile
yarn clean
yarn compile
# Check Solidity version
npx hardhat --version# Re-run security setup
.devcontainer/scripts/setup-security.sh
# Check tool versions
semgrep --version
slither --version# Check port usage
lsof -i :8545
# Change ports in docker-compose.yml or configure in .env
ports:
- "8547:8545" # Map host 8547 to container 8545# Reinstall git hooks
git secrets --install
# Clear secrets cache
rm -rf .git/git-secrets- Increase Docker memory allocation (4GB+ recommended)
- Use volume mounts for better I/O performance
- Enable Docker BuildKit:
export DOCKER_BUILDKIT=1
# Enable Hardhat cache
export HARDHAT_CACHE_DIR=./cache
# Use parallel compilation
npx hardhat compile --parallel# Test network connectivity
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
http://localhost:${HARDHAT_PORT:-8545}- Check API key validity
- Verify network endpoints
- Check rate limits
Diamonds uses ERC-2535 Diamond Proxy Standard for upgradeable contracts:
Diamond (Proxy)
βββ Facet A (Access Control)
βββ Facet B (Treasury)
βββ Facet C (Governance)
βββ Facet D (Member Management)
-
Create Facet:
contract DiamondAccessControlFacet { // Facet logic here }
-
Add to Diamond:
await diamondCut.facetCuts([ { facetAddress: accessControlFacet.address, action: FacetCutAction.Add, functionSelectors: getSelectors(accessControlFacet), }, ]);
-
Generate Types:
npx hardhat diamond:generate-abi-typechain --diamond-name <DIAMOND_NAME>
- Use
LibDiamondfor standard diamond operations - Implement proper storage patterns
- Test facet isolation thoroughly
- Validate upgrade compatibility
- Monitor gas usage for diamond cuts
- Ethereum Mainnet
- Sepolia Testnet
- Polygon Mainnet/Mumbai
- Arbitrum One/Sepolia
- Base Mainnet/Sepolia
# Fork mainnet for testing
npx hardhat node --fork https://mainnet.infura.io/v3/YOUR_KEY
# Run tests against fork
npx hardhat test --network hardhat# Deploy to testnet
npx hardhat run scripts/deploy/ --network sepolia
# Verify contracts
npx hardhat verify --network sepolia CONTRACT_ADDRESS# Check container status
docker ps
# View logs
docker-compose logs devcontainer
# Health check
curl http://localhost:8545 \
-X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'# Monitor resource usage
docker stats
# Check disk usage
docker system df
# Clean up
docker system prune- Security First: All changes must pass security scans
- Test Coverage: Maintain 90%+ test coverage
- Code Quality: Follow ESLint/Prettier rules
- Documentation: Update docs for API changes
- Create feature branch
- Run full test suite:
yarn test - Run security checks:
yarn security-check - Update documentation
- Create PR with detailed description
- Check this README for common issues
- Review VS Code output for error messages
- Check container logs:
docker-compose logs - Validate environment:
.devcontainer/scripts/github-actions-setup.sh
- Bug Reports: Create GitHub issue with full error logs
- Security Issues: Report via SECURITY.md process
- Performance Issues: Include
docker statsoutput
This DevContainer configuration is part of the Diamonds project. See project LICENSE for details.
This DevContainer setup is designed to be portable and reusable across multiple projects. It can be used as a submodule in different repositories.
The devcontainer uses environment variables to make it portable. The main configuration is controlled by the WORKSPACE_NAME variable.
-
Copy the
.env.examplefile to.env:cp .devcontainer/.env.example .devcontainer/.env
-
Edit
.envand set your workspace name:WORKSPACE_NAME=your-project-name
Important: Use underscores (
_) instead of hyphens (-) in the workspace name for compatibility with Docker Compose network naming.
WORKSPACE_NAME: The name of your workspace/project. This will be used for:- Docker workspace paths (
/workspaces/${WORKSPACE_NAME}) - Docker network naming (
${WORKSPACE_NAME}-network) - Volume mount paths
- Docker workspace paths (
If WORKSPACE_NAME is not set in the .env file, the devcontainer will use the default value: diamonds-dev-env
To use this devcontainer in another project:
-
Add as a submodule:
git submodule add <repository-url> .devcontainer
-
Copy the
.env.exampleto.env:cp .devcontainer/.env.example .devcontainer/.env
-
Configure your workspace name:
echo "WORKSPACE_NAME=my_new_project" > .devcontainer/.env
-
Open in VS Code:
- Press
F1orCtrl+Shift+P - Select "Dev Containers: Reopen in Container"
- Press
The following files use the WORKSPACE_NAME variable:
- Dockerfile: Creates workspace directories based on
WORKSPACE_NAME - docker-compose.yml: Configures volumes, networks, and paths using
WORKSPACE_NAME - devcontainer.json: Sets workspace folder and mount points using
WORKSPACE_NAME
- Recommended: Use underscores (
_) instead of hyphens (-)- β
Good:
diamonds_dev_env,my_project_name - β Avoid:
diamonds-dev-env,my-project-name
- β
Good:
This is because Docker Compose has restrictions on network names and will automatically convert hyphens to underscores, which can cause confusion.
| Project Name | WORKSPACE_NAME | Docker Network |
|---|---|---|
| diamonds-dev-env | diamonds_dev_env |
diamonds_dev_env-network |
| diamonds-project | diamonds_project |
diamonds_project-network |
| my-new-project | my_new_project |
my_new_project-network |
The DevContainer uses environment variables from three sources:
- Host Environment Variables (build-time) - Set on your host machine, used during container build
- Container Environment Variables (runtime) - Set in
devcontainer.json, available in running container - .env File Variables (application-level) - Used by Hardhat and scripts, loaded at runtime
See ENV_VARS.md for detailed documentation.
- WORKSPACE_NAME: Name of the workspace directory (default:
diamonds_project) - DIAMOND_NAME: Name of the diamond contract to work with (default:
ExampleDiamond)
# On your HOST machine (before opening DevContainer)
source .devcontainer/set-host-env.sh
# Then rebuild the container# On your HOST machine
export WORKSPACE_NAME=diamonds_dev_env
export DIAMOND_NAME=ExampleDiamond
# Then rebuild the containerThe .env file values are used as fallback by scripts:
WORKSPACE_NAME=diamonds_dev_env
DIAMOND_NAME=ExampleDiamondNote: The .env file is NOT read during container build, only at runtime.
- Check that
.envfile exists in.devcontainer/ - Verify
WORKSPACE_NAMEis set and doesn't contain special characters - Try rebuilding without cache:
docker-compose -f .devcontainer/docker-compose.yml build --no-cache
- Ensure the
WORKSPACE_NAMEin.envmatches your project structure - Check Docker has permission to access your workspace folder
- Verify all required directories exist or will be created by the container
If you see network naming errors, ensure WORKSPACE_NAME uses underscores instead of hyphens.
You can use this devcontainer for multiple projects by:
- Using different
WORKSPACE_NAMEvalues for each project - Ensuring each project has its own
.envfile in the.devcontainerdirectory - Each project will have isolated Docker networks and volumes
When contributing to this devcontainer setup:
- Never hardcode project-specific paths
- Use
${WORKSPACE_NAME}or${localEnv:WORKSPACE_NAME:default-value}for all paths - Update this README with any new configuration options
- Test with different
WORKSPACE_NAMEvalues to ensure portability
Happy coding! π
Built with β€οΈ for secure, scalable DeFi development