Initial commit: add .gitignore and README

This commit is contained in:
defiQUG
2026-02-09 21:51:30 -08:00
commit 47f6f2de7b
92 changed files with 15299 additions and 0 deletions

310
docs/CHAIN_CONFIG.md Normal file
View File

@@ -0,0 +1,310 @@
# 🔗 Chain Configuration Guide
How to add and configure new chains in the DeFi Starter Kit.
---
## 📋 Overview
This guide walks you through adding a new blockchain network to the DeFi Starter Kit. You'll need to configure:
- 🔗 RPC endpoints
- 📍 Protocol contract addresses
- 💰 Token addresses
- 🔧 Viem chain configuration
---
## 🚀 Adding a New Chain
### 1⃣ Create Chain Config File
Create a new file in `config/chains/` with your chain configuration:
```typescript
// config/chains/yourchain.ts
import type { ChainConfig } from '../types.js';
export const yourchain: ChainConfig = {
chainId: 12345, // Your chain ID
name: 'Your Chain',
rpcUrl: process.env.YOURCHAIN_RPC_URL || 'https://rpc.yourchain.com',
// Aave v3
aave: {
poolAddressesProvider: '0x...', // Aave PoolAddressesProvider
pool: '0x...', // Aave Pool
},
// Uniswap
uniswap: {
swapRouter02: '0x...', // Uniswap SwapRouter02
universalRouter: '0x...', // Uniswap Universal Router
permit2: '0x000000000022D473030F116dDEE9F6B43aC78BA3', // Permit2 (same across chains)
quoterV2: '0x...', // Uniswap QuoterV2
},
// Protocolink
protocolink: {
router: '0x...', // Protocolink Router
},
// Compound III
compound3: {
cometUsdc: '0x...', // Compound III Comet (if available)
},
// Common Tokens
tokens: {
WETH: '0x...',
USDC: '0x...',
USDT: '0x...',
DAI: '0x...',
WBTC: '0x...',
},
};
```
### 2⃣ Register Chain in Addresses
Add your chain to `config/addresses.ts`:
```typescript
import { yourchain } from './chains/yourchain.js';
export const chainConfigs: Record<number, ChainConfig> = {
1: mainnet,
8453: base,
// ... other chains
12345: yourchain, // Add your chain
};
// Re-export
export { yourchain };
```
### 3⃣ Add Viem Chain
Add your chain to `src/utils/chain-config.ts`:
```typescript
import { yourChain } from 'viem/chains';
const viemChains = {
1: mainnet,
8453: base,
// ... other chains
12345: yourChain, // Add your chain
};
```
### 4⃣ Update Environment Variables
Add RPC URL to `.env.example`:
```bash
YOURCHAIN_RPC_URL=https://rpc.yourchain.com
```
### 5⃣ Update Foundry Config
Add RPC endpoint to `foundry.toml`:
```toml
[rpc_endpoints]
yourchain = "${YOURCHAIN_RPC_URL}"
```
---
## 📍 Getting Official Addresses
### 🏦 Aave v3
1. 📚 Check [Aave Documentation](https://docs.aave.com/developers/deployed-contracts/deployed-contracts)
2. 🔍 Find your chain in the deployed contracts list
3. 📋 Get `PoolAddressesProvider` address
4. 🔗 Use `PoolAddressesProvider.getPool()` to get Pool address
### 🔄 Uniswap v3
1. 📚 Check [Uniswap Deployments](https://docs.uniswap.org/contracts/v3/reference/deployments)
2. 🔍 Find your chain's deployment page
3. 📋 Get addresses for:
- `SwapRouter02`
- `UniversalRouter`
- `Permit2` (same address across all chains: `0x000000000022D473030F116dDEE9F6B43aC78BA3`)
- `QuoterV2`
### 🔗 Protocolink
1. 📚 Check [Protocolink Deployment Addresses](https://docs.protocolink.com/smart-contract/deployment-addresses)
2. 🔍 Find your chain
3. 📋 Get Router address
### 🏛️ Compound III
1. 📚 Check [Compound III Documentation](https://docs.compound.finance/)
2. 🔍 Find your chain's Comet addresses
3. 📋 Get Comet proxy address for your market
### 💰 Common Tokens
For each chain, you'll need addresses for:
| Token | Description |
|-------|-------------|
| WETH | Wrapped Ether |
| USDC | USD Coin |
| USDT | Tether USD |
| DAI | Dai Stablecoin |
| WBTC | Wrapped Bitcoin |
**Resources:**
- 🔍 [Token Lists](https://tokenlists.org/)
- 🔍 [CoinGecko](https://www.coingecko.com/)
---
## ✅ Verifying Addresses
Always verify addresses from multiple sources:
1. ✅ Official protocol documentation
2. ✅ Block explorer (verify contract code)
3. ✅ Protocol GitHub repositories
4. ✅ Community resources (Discord, forums)
---
## 🧪 Testing Your Configuration
After adding a new chain:
### 1. Test Chain Config Loading
```typescript
import { getChainConfig } from './config/addresses.js';
const config = getChainConfig(12345);
console.log(config);
```
### 2. Test RPC Connection
```typescript
import { createRpcClient } from './src/utils/chain-config.js';
const client = createRpcClient(12345);
const blockNumber = await client.getBlockNumber();
console.log('Block number:', blockNumber);
```
### 3. Test Address Resolution
```typescript
import { getAavePoolAddress } from './src/utils/addresses.js';
const poolAddress = getAavePoolAddress(12345);
console.log('Pool address:', poolAddress);
```
### 4. Run Examples
```bash
# Update example to use your chain ID
tsx examples/ts/aave-supply-borrow.ts
```
### 5. Run Tests
```bash
# Update test to use your chain
forge test --fork-url $YOURCHAIN_RPC_URL
```
---
## 🔧 Common Issues
### ❌ RPC URL Not Working
**Possible causes:**
- ❌ RPC URL is incorrect
- ❌ RPC provider doesn't support your chain
- ❌ Rate limits exceeded
**Solutions:**
- ✅ Verify RPC URL is correct
- ✅ Try alternative RPC providers
- ✅ Check rate limits
### ❌ Addresses Not Found
**Possible causes:**
- ❌ Protocol not deployed on your chain
- ❌ Addresses are incorrect (typos, wrong network)
- ❌ Some protocols may not be available on all chains
**Solutions:**
- ✅ Verify protocol is deployed on your chain
- ✅ Double-check addresses for typos
- ✅ Check protocol documentation for chain support
### ❌ Token Addresses Wrong
**Possible causes:**
- ❌ Token addresses are incorrect
- ❌ Token decimals differ
- ❌ Tokens don't exist on your chain
**Solutions:**
- ✅ Verify token addresses on block explorer
- ✅ Check token decimals
- ✅ Ensure tokens exist on your chain
---
## 📝 Chain-Specific Notes
### 🚀 Layer 2 Chains
| Consideration | Description |
|---------------|-------------|
| Gas costs | Typically lower than mainnet |
| Finality times | May differ from mainnet |
| Protocol features | Some protocols may have L2-specific features |
### 🧪 Testnets
| Consideration | Description |
|---------------|-------------|
| Addresses | Use testnet-specific addresses |
| Tokens | Testnet tokens have no real value |
| Protocol availability | Some protocols may not be available on testnets |
---
## 💡 Best Practices
1.**Always verify addresses** - Don't trust a single source
2.**Use environment variables** - Never hardcode RPC URLs
3.**Test thoroughly** - Test on testnet before mainnet
4.**Document changes** - Update documentation when adding chains
5.**Keep addresses updated** - Protocols may upgrade contracts
---
## 🔗 Resources
| Resource | Link |
|----------|------|
| Aave Deployed Contracts | [docs.aave.com](https://docs.aave.com/developers/deployed-contracts/deployed-contracts) |
| Uniswap Deployments | [docs.uniswap.org](https://docs.uniswap.org/contracts/v3/reference/deployments) |
| Protocolink Deployment Addresses | [docs.protocolink.com](https://docs.protocolink.com/smart-contract/deployment-addresses) |
| Compound III Documentation | [docs.compound.finance](https://docs.compound.finance/) |
---
## 📚 Related Documentation
- 📖 [Environment Setup Guide](./ENV_SETUP.md)
- 🔐 [Security Best Practices](./SECURITY.md)
- 🧪 [Strategy Testing Guide](./STRATEGY_TESTING.md)

View File

@@ -0,0 +1,224 @@
# ✅ Environment Setup - Verification Complete
## 🎉 All Scripts Verified
All scripts have been verified to properly load environment variables from `.env` files.
---
## ✅ Scripts Checked
### 1. `src/strat/cli.ts` ✅
- ✅ Loads `dotenv` FIRST before any other imports
- ✅ Uses `getNetwork()` which lazy-loads RPC URLs from env vars
- ✅ Validates RPC URLs and shows helpful error messages
### 2. `src/cli/cli.ts` ✅
- ✅ Loads `dotenv` FIRST before any other imports
- ✅ Uses `process.env.PRIVATE_KEY` for transaction execution
- ✅ Uses RPC URLs from chain configs (which read from env)
### 3. `scripts/test-strategy.ts` ✅
- ✅ Loads `dotenv` FIRST before any other imports
- ✅ Reads `MAINNET_RPC_URL`, `TEST_SCENARIO`, `TEST_NETWORK` from env
- ✅ Validates RPC URL before proceeding
- ✅ Shows clear error messages if not configured
### 4. `scripts/check-env.ts` ✅
- ✅ Loads `dotenv` FIRST
- ✅ Verifies all RPC URLs are set and accessible
- ✅ Tests connections to each network
- ✅ Provides helpful feedback
### 5. `scripts/verify-setup.ts` ✅
- ✅ Loads `dotenv` FIRST
- ✅ Comprehensive verification of all setup components
- ✅ Checks scripts, configs, and scenarios
---
## ⚙️ Network Configuration
### `src/strat/config/networks.ts` ✅
- ✅ Lazy-loads RPC URLs when `getNetwork()` is called
- ✅ Ensures `dotenv` is loaded before reading env vars
- ✅ Supports network-specific env vars (e.g., `MAINNET_RPC_URL`)
- ✅ Falls back to defaults if not set
### `config/chains/*.ts` ✅
- ✅ Read `process.env` at module load time
- ✅ Since all entry points load `dotenv` FIRST, this works correctly
- ✅ Have sensible defaults as fallbacks
---
## 📋 Environment Variables
### Required
| Variable | Description | Status |
|----------|-------------|--------|
| `MAINNET_RPC_URL` | For mainnet fork testing (required for most scenarios) | ✅ |
### Optional
| Variable | Description | When Needed |
|----------|-------------|-------------|
| `BASE_RPC_URL` | For Base network testing | Multi-chain testing |
| `ARBITRUM_RPC_URL` | For Arbitrum testing | Multi-chain testing |
| `OPTIMISM_RPC_URL` | For Optimism testing | Multi-chain testing |
| `POLYGON_RPC_URL` | For Polygon testing | Multi-chain testing |
| `PRIVATE_KEY` | Only needed for mainnet execution (not fork testing) | Mainnet execution |
| `TEST_SCENARIO` | Override default test scenario | Custom scenarios |
| `TEST_NETWORK` | Override default test network | Multi-chain testing |
---
## ✅ Validation
All scripts now include:
- ✅ RPC URL validation (checks for placeholders)
- ✅ Clear error messages if not configured
- ✅ Helpful suggestions (e.g., "Run 'pnpm run check:env'")
- ✅ Fallback to defaults where appropriate
---
## 🧪 Testing
Run these commands to verify your setup:
```bash
# 1. Check environment variables
pnpm run check:env
# 2. Verify complete setup
pnpm run verify:setup
# 3. Test with a scenario (requires valid RPC URL)
pnpm run strat:test
```
---
## 🔧 How It Works
### 1. Entry Point (CLI script or test script)
- 📥 Loads `dotenv.config()` FIRST
- 📄 This reads `.env` file into `process.env`
### 2. Network Configuration
- 🔗 `getNetwork()` is called
- ⚡ Lazy-loads RPC URLs from `process.env`
- ✅ Returns network config with RPC URL
### 3. Fork Orchestrator
- 🔌 Uses the RPC URL from network config
- 🌐 Connects to the RPC endpoint
- 🍴 Creates fork if needed
### 4. Validation
- ✅ Scripts validate RPC URLs before use
- 🔍 Check for placeholders like "YOUR_KEY"
- 💬 Show helpful error messages if invalid
---
## 🔧 Troubleshooting
If environment variables aren't loading:
### 1. Check .env file exists
```bash
ls -la .env
```
### 2. Verify dotenv is loaded first
- ✅ Check that `import dotenv from 'dotenv'` and `dotenv.config()` are at the top
- ✅ Before any other imports that use `process.env`
### 3. Test environment loading
```bash
node -e "require('dotenv').config(); console.log(process.env.MAINNET_RPC_URL)"
```
### 4. Run verification
```bash
pnpm run verify:setup
```
---
## 💡 Best Practices
### 1. Always load dotenv first
```typescript
// ✅ Good
import dotenv from 'dotenv';
dotenv.config();
import { other } from './other.js';
```
### 2. Use lazy-loading for configs
```typescript
// ✅ Good - lazy load
function getNetwork() {
return { rpcUrl: process.env.MAINNET_RPC_URL || 'default' };
}
```
### 3. Validate before use
```typescript
// ✅ Good - validate
if (!rpcUrl || rpcUrl.includes('YOUR_KEY')) {
throw new Error('RPC URL not configured');
}
```
---
## 📊 Summary
| Check | Status | Description |
|-------|--------|-------------|
| Scripts load `.env` files | ✅ | All scripts properly load `.env` files |
| RPC URL validation | ✅ | All scripts validate RPC URLs before use |
| Lazy-loading configs | ✅ | Network configs lazy-load to ensure env vars are available |
| Clear error messages | ✅ | Clear error messages guide users to fix issues |
| Verification scripts | ✅ | Verification scripts help diagnose problems |
| Documentation | ✅ | Documentation explains the setup process |
---
## 🎉 Conclusion
The environment setup is complete and verified! ✅
All scripts are properly connected to `.env` files and handle secrets correctly. You're ready to start building DeFi strategies!
---
## 📚 Related Documentation
- 📖 [Environment Setup Guide](./ENV_SETUP.md)
- ✅ [Verification Summary](./ENV_VERIFICATION_SUMMARY.md)
- 🧪 [Strategy Testing Guide](./STRATEGY_TESTING.md)

261
docs/ENV_SETUP.md Normal file
View File

@@ -0,0 +1,261 @@
# ⚙️ Environment Setup Guide
This guide explains how to set up environment variables for the DeFi Strategy Testing Framework.
---
## 🚀 Quick Start
### 1⃣ Copy the Example Environment File
```bash
cp .env.example .env
```
### 2⃣ Fill in Your RPC URLs
```bash
# Edit .env file
MAINNET_RPC_URL=https://mainnet.infura.io/v3/YOUR_INFURA_KEY
BASE_RPC_URL=https://base-mainnet.infura.io/v3/YOUR_INFURA_KEY
# ... etc
```
### 3⃣ Verify Your Setup
```bash
pnpm run check:env
```
---
## 📋 Required Environment Variables
### 🔗 RPC URLs
These are used to connect to blockchain networks for forking and testing:
| Variable | Description | Required |
|----------|-------------|----------|
| `MAINNET_RPC_URL` | Ethereum mainnet RPC endpoint | ✅ Yes |
| `BASE_RPC_URL` | Base network RPC endpoint | ⚠️ Optional |
| `ARBITRUM_RPC_URL` | Arbitrum One RPC endpoint | ⚠️ Optional |
| `OPTIMISM_RPC_URL` | Optimism network RPC endpoint | ⚠️ Optional |
| `POLYGON_RPC_URL` | Polygon network RPC endpoint | ⚠️ Optional |
### 🔐 Optional Environment Variables
| Variable | Description | When Needed |
|----------|-------------|-------------|
| `PRIVATE_KEY` | Private key for executing transactions | Mainnet/testnet execution only |
| `TEST_SCENARIO` | Override default test scenario path | Custom test scenarios |
| `TEST_NETWORK` | Override default test network | Multi-chain testing |
---
## 🔗 Getting RPC URLs
### 🆓 Free Options
#### 1. Public RPCs (Rate-Limited)
| Network | Public RPC URL |
|---------|----------------|
| Ethereum | `https://eth.llamarpc.com` |
| Base | `https://mainnet.base.org` |
| Arbitrum | `https://arb1.arbitrum.io/rpc` |
| Optimism | `https://mainnet.optimism.io` |
| Polygon | `https://polygon-rpc.com` |
#### 2. Infura (Free Tier)
1. 📝 Sign up at [infura.io](https://infura.io)
2. Create a project
3. 📋 Copy your project ID
4. 🔗 Use: `https://mainnet.infura.io/v3/YOUR_PROJECT_ID`
#### 3. Alchemy (Free Tier)
1. 📝 Sign up at [alchemy.com](https://alchemy.com)
2. Create an app
3. 📋 Copy your API key
4. 🔗 Use: `https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY`
### 💰 Paid Options (Recommended for Production)
| Provider | Best For | Link |
|----------|----------|------|
| **Infura** | Reliable, well-known | [infura.io](https://infura.io) |
| **Alchemy** | Fast, good free tier | [alchemy.com](https://alchemy.com) |
| **QuickNode** | Fast, global network | [quicknode.com](https://quicknode.com) |
| **Ankr** | Good performance | [ankr.com](https://ankr.com) |
---
## ✅ Verification
### 🔍 Check Environment Variables
Run the environment checker:
```bash
pnpm run check:env
```
This will:
- ✅ Check that all RPC URLs are set
- ✅ Verify connections to each network
- ✅ Show current block numbers
- ✅ Report any issues
### 🧪 Test with a Scenario
```bash
# Set your RPC URL
export MAINNET_RPC_URL=https://your-rpc-url-here
# Run a test
pnpm run strat:test
```
---
## 🔧 Troubleshooting
### ❌ "RPC URL contains placeholder"
**Problem:** Your `.env` file still has placeholder values like `YOUR_KEY` or `YOUR_INFURA_KEY`.
**Solution:** Replace placeholders with actual RPC URLs in your `.env` file.
### ❌ "Connection failed" or "403 Forbidden"
**Problem:** Your RPC endpoint is rejecting requests.
**Possible Causes:**
1. ❌ Invalid API key
2. ⏱️ Rate limiting (free tier exceeded)
3. 🚫 IP restrictions
4. 🔒 Infura project set to "private key only" mode
**Solutions:**
1. ✅ Verify your API key is correct
2. ✅ Check your RPC provider dashboard for rate limits
3. ✅ Try a different RPC provider
4. ✅ For Infura: Enable "Public Requests" in project settings
### ❌ "Environment variable not set"
**Problem:** The script can't find the required environment variable.
**Solutions:**
1. ✅ Check that `.env` file exists in project root
2. ✅ Verify variable name is correct (case-sensitive)
3. ✅ Restart your terminal/IDE after creating `.env`
4. ✅ Use `pnpm run check:env` to verify
### ❌ Module Load Order Issues
**Problem:** Environment variables not being loaded before modules that use them.
**Solution:** The framework now loads `dotenv` FIRST in all entry points. If you still have issues:
1. ✅ Ensure `.env` file is in the project root
2. ✅ Check that `dotenv` package is installed
3. ✅ Verify scripts load dotenv before other imports
---
## 💡 Best Practices
### 🔐 Security
1. **Never commit `.env` files:**
-`.env` is in `.gitignore`
- ✅ Only commit `.env.example`
2. **Use different keys for different environments:**
- 🧪 Development: Free tier or public RPCs
- 🚀 Production: Paid RPC providers
3. **Rotate keys regularly:**
- 🔄 Especially if keys are exposed
- 📝 Update `.env` file with new keys
### 🗂️ Organization
4. **Use environment-specific files:**
- 📁 `.env.local` - Local development (gitignored)
- 📁 `.env.production` - Production (gitignored)
- 📁 `.env.example` - Template (committed)
5. **Validate on startup:**
- ✅ Use `pnpm run check:env` before running tests
- ✅ Scripts will warn if RPC URLs are not configured
---
## 🔒 Security Notes
> ⚠️ **IMPORTANT**:
> - ⛔ **Never commit `.env` files** - They may contain private keys
> - 🔑 **Don't share RPC keys** - They may have rate limits or costs
> - 🔄 **Use separate keys** for development and production
> - 🔐 **Rotate keys** if they're exposed or compromised
---
## 📝 Example .env File
```bash
# RPC Endpoints
MAINNET_RPC_URL=https://mainnet.infura.io/v3/your-infura-project-id
BASE_RPC_URL=https://base-mainnet.infura.io/v3/your-infura-project-id
ARBITRUM_RPC_URL=https://arbitrum-mainnet.infura.io/v3/your-infura-project-id
OPTIMISM_RPC_URL=https://optimism-mainnet.infura.io/v3/your-infura-project-id
POLYGON_RPC_URL=https://polygon-mainnet.infura.io/v3/your-infura-project-id
# Private Keys (only for mainnet execution, not fork testing)
# PRIVATE_KEY=0x...
# Test Configuration (optional)
# TEST_SCENARIO=scenarios/aave/leveraged-long.yml
# TEST_NETWORK=mainnet
```
---
## 🎯 Next Steps
After setting up your environment:
### 1. Verify Setup
```bash
pnpm run check:env
```
### 2. Run a Test Scenario
```bash
pnpm run strat:test
```
### 3. Run a Scenario with CLI
```bash
pnpm run strat run scenarios/aave/leveraged-long.yml
```
### 4. Try Fuzzing
```bash
pnpm run strat fuzz scenarios/aave/leveraged-long.yml --iters 10
```
---
## 📚 Related Documentation
- 📖 [Strategy Testing Guide](./STRATEGY_TESTING.md)
- 🔗 [Chain Configuration](./CHAIN_CONFIG.md)
- 🔐 [Security Best Practices](./SECURITY.md)

View File

@@ -0,0 +1,147 @@
# ✅ Environment Setup Verification - Complete
## 🎉 Verification Results
All scripts have been verified to properly connect to `.env` files and handle secrets correctly.
---
## ✅ Scripts Verified
### 1. `src/strat/cli.ts` ✅
- ✅ Loads `dotenv` FIRST (line 14-15)
- ✅ Before any other imports
- ✅ Validates RPC URLs before use
- ✅ Shows helpful error messages
### 2. `src/cli/cli.ts` ✅
- ✅ Loads `dotenv` FIRST (line 13-15)
- ✅ Before any other imports
- ✅ Uses `PRIVATE_KEY` from env for execution
- ✅ Validates private key before use
### 3. `scripts/test-strategy.ts` ✅
- ✅ Loads `dotenv` FIRST (line 18-19)
- ✅ Before any other imports
- ✅ Reads `MAINNET_RPC_URL`, `TEST_SCENARIO`, `TEST_NETWORK`
- ✅ Validates RPC URL with placeholder checks
- ✅ Shows clear error messages
### 4. `scripts/check-env.ts` ✅
- ✅ Loads `dotenv` FIRST
- ✅ Tests all RPC URL connections
- ✅ Validates environment setup
- ✅ Provides detailed feedback
### 5. `scripts/verify-setup.ts` ✅
- ✅ Loads `dotenv` FIRST
- ✅ Comprehensive setup verification
- ✅ Checks all components
---
## ✅ Configuration Verified
### 1. `src/strat/config/networks.ts` ✅
- ✅ Lazy-loads RPC URLs when `getNetwork()` is called
- ✅ Ensures `dotenv` is loaded before reading env vars
- ✅ Supports all network-specific env vars
- ✅ Has sensible fallbacks
### 2. `config/chains/*.ts` ✅
- ✅ Read `process.env` at module load
- ✅ Work correctly because entry points load dotenv first
- ✅ Have default fallbacks
---
## 📋 Environment Variables
### Required
| Variable | Description | Status |
|----------|-------------|--------|
| `MAINNET_RPC_URL` | Required for mainnet fork testing | ✅ |
### Optional
| Variable | Description | When Needed |
|----------|-------------|-------------|
| `BASE_RPC_URL` | Base network RPC endpoint | Multi-chain testing |
| `ARBITRUM_RPC_URL` | Arbitrum One RPC endpoint | Multi-chain testing |
| `OPTIMISM_RPC_URL` | Optimism network RPC endpoint | Multi-chain testing |
| `POLYGON_RPC_URL` | Polygon network RPC endpoint | Multi-chain testing |
| `PRIVATE_KEY` | Private key for executing transactions | Mainnet/testnet execution only |
| `TEST_SCENARIO` | Override default test scenario path | Custom test scenarios |
| `TEST_NETWORK` | Override default test network | Multi-chain testing |
---
## ✅ Validation Features
All scripts include:
- ✅ RPC URL validation (checks for placeholders like "YOUR_KEY")
- ✅ Clear error messages if not configured
- ✅ Helpful suggestions (e.g., "Run 'pnpm run check:env'")
- ✅ Fallback to defaults where appropriate
---
## 🔧 Verification Commands
```bash
# Check environment variables and RPC connections
pnpm run check:env
# Verify complete setup
pnpm run verify:setup
# Test with a scenario
pnpm run strat:test
```
---
## 🔐 Security
| Check | Status | Description |
|-------|--------|-------------|
| `.env` in `.gitignore` | ✅ | `.env` file is in `.gitignore` |
| `.env.example` template | ✅ | `.env.example` provides template |
| Private keys protection | ✅ | Private keys only used when explicitly needed |
| RPC URL validation | ✅ | RPC URLs validated before use |
| No hardcoded secrets | ✅ | No hardcoded secrets |
---
## 🧪 Test Results
Running `pnpm run verify:setup` shows:
- ✅ All scripts load dotenv correctly
- ✅ Network config loads correctly
- ✅ Scenario files exist
- ✅ Environment variables are accessible
---
## 🎉 Conclusion
All scripts are properly connected to `.env` files and handle secrets correctly. The setup is complete and ready for use!
---
## 📚 Next Steps
1. ✅ Run `pnpm run check:env` to verify your environment
2. ✅ Run `pnpm run verify:setup` for comprehensive verification
3. ✅ Test with `pnpm run strat:test`
4. ✅ Start building DeFi strategies!

320
docs/INTEGRATION_GUIDE.md Normal file
View File

@@ -0,0 +1,320 @@
# 🔌 Integration Guide
> Step-by-step guide for integrating DeFi protocols into your application.
---
## 📋 Table of Contents
1. [Aave v3 Integration](#-aave-v3-integration)
2. [Uniswap v3 Integration](#-uniswap-v3-integration)
3. [Protocolink Integration](#-protocolink-integration)
4. [Compound III Integration](#-compound-iii-integration)
5. [Cross-Protocol Strategies](#-cross-protocol-strategies)
---
## 🏦 Aave v3 Integration
### 1⃣ Setup
```typescript
import { createWalletRpcClient } from '../src/utils/chain-config.js';
import { getAavePoolAddress } from '../src/utils/addresses.js';
const CHAIN_ID = 1; // Mainnet
const walletClient = createWalletRpcClient(CHAIN_ID, privateKey);
const poolAddress = getAavePoolAddress(CHAIN_ID);
```
### 2⃣ Supply Collateral
```typescript
// 1. Approve token
await walletClient.writeContract({
address: tokenAddress,
abi: ERC20_ABI,
functionName: 'approve',
args: [poolAddress, amount],
});
// 2. Supply
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'supply',
args: [asset, amount, account, 0],
});
// 3. Enable as collateral
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'setUserUseReserveAsCollateral',
args: [asset, true],
});
```
### 3⃣ Borrow
```typescript
// Note: Use variable rate (2), stable rate is deprecated in v3.3+
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'borrow',
args: [debtAsset, borrowAmount, 2, 0, account],
});
```
### 4⃣ Flash Loans
#### Single Asset
```typescript
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'flashLoanSimple',
args: [receiverAddress, asset, amount, params, 0],
});
```
#### Multi-Asset
```typescript
await walletClient.writeContract({
address: poolAddress,
abi: POOL_ABI,
functionName: 'flashLoan',
args: [receiverAddress, assets, amounts, modes, account, params, 0],
});
```
> ⚠️ **Important**: Your flash loan receiver contract must:
> 1. ✅ Receive the loaned tokens
> 2. ✅ Perform desired operations
> 3. ✅ Approve the pool for `amount + premium`
> 4. ✅ Return `true` from `executeOperation`
---
## 🔄 Uniswap v3 Integration
### 1⃣ Setup
```typescript
import { getUniswapSwapRouter02 } from '../src/utils/addresses.js';
const routerAddress = getUniswapSwapRouter02(CHAIN_ID);
```
### 2⃣ Get Quote
```typescript
// Use QuoterV2 contract to get expected output
const quote = await publicClient.readContract({
address: quoterAddress,
abi: QUOTER_ABI,
functionName: 'quoteExactInputSingle',
args: [{
tokenIn: tokenInAddress,
tokenOut: tokenOutAddress,
fee: 3000, // 0.3% fee tier
amountIn: amountIn,
sqrtPriceLimitX96: 0,
}],
});
```
### 3⃣ Execute Swap
```typescript
// 1. Approve token
await walletClient.writeContract({
address: tokenInAddress,
abi: ERC20_ABI,
functionName: 'approve',
args: [routerAddress, amountIn],
});
// 2. Execute swap
await walletClient.writeContract({
address: routerAddress,
abi: SWAP_ROUTER_ABI,
functionName: 'exactInputSingle',
args: [{
tokenIn: tokenInAddress,
tokenOut: tokenOutAddress,
fee: 3000,
recipient: account,
deadline: BigInt(Math.floor(Date.now() / 1000) + 600),
amountIn: amountIn,
amountOutMinimum: amountOutMin, // Apply slippage protection
sqrtPriceLimitX96: 0,
}],
});
```
### 4⃣ TWAP Oracle
```typescript
// Always use TWAP, not spot prices, to protect against manipulation
// See examples/ts/uniswap-v3-oracle.ts for implementation
```
---
## 🔗 Protocolink Integration
### 1⃣ Setup
```typescript
import * as api from '@protocolink/api';
import * as common from '@protocolink/common';
const CHAIN_ID = common.ChainId.mainnet;
```
### 2⃣ Build Logics
```typescript
// Swap logic
const swapQuotation = await api.protocols.uniswapv3.getSwapTokenQuotation(CHAIN_ID, {
input: { token: USDC, amount: '1000' },
tokenOut: WBTC,
slippage: 100,
});
const swapLogic = api.protocols.uniswapv3.newSwapTokenLogic(swapQuotation);
// Supply logic
const supplyQuotation = await api.protocols.aavev3.getSupplyQuotation(CHAIN_ID, {
input: swapQuotation.output,
});
const supplyLogic = api.protocols.aavev3.newSupplyLogic(supplyQuotation);
```
### 3⃣ Execute
```typescript
const routerData = await api.router.getRouterData(CHAIN_ID, {
account,
logics: [swapLogic, supplyLogic],
});
await walletClient.sendTransaction({
to: routerData.router,
data: routerData.data,
value: BigInt(routerData.estimation.value || '0'),
gas: BigInt(routerData.estimation.gas),
});
```
---
## 🏛️ Compound III Integration
### 1⃣ Setup
```typescript
import { getCompound3Comet } from '../src/utils/addresses.js';
const cometAddress = getCompound3Comet(CHAIN_ID);
```
### 2⃣ Supply Collateral
```typescript
// 1. Approve collateral
await walletClient.writeContract({
address: collateralAddress,
abi: ERC20_ABI,
functionName: 'approve',
args: [cometAddress, amount],
});
// 2. Supply
await walletClient.writeContract({
address: cometAddress,
abi: COMET_ABI,
functionName: 'supply',
args: [collateralAddress, amount],
});
```
### 3⃣ Borrow Base Asset
```typescript
// In Compound III, you "borrow" by withdrawing the base asset
const baseToken = await publicClient.readContract({
address: cometAddress,
abi: COMET_ABI,
functionName: 'baseToken',
});
await walletClient.writeContract({
address: cometAddress,
abi: COMET_ABI,
functionName: 'withdraw',
args: [baseToken, borrowAmount],
});
```
---
## 🔄 Cross-Protocol Strategies
### ⚡ Flash Loan Arbitrage
**Strategy Flow:**
1. ⚡ Flash loan asset from Aave
2. 🔄 Swap on Uniswap (or other DEX)
3. 🔄 Swap on different DEX/pool
4. ✅ Repay flash loan + premium
5. 💰 Keep profit
> 📖 See `examples/ts/flashloan-arbitrage.ts` for conceptual example.
### 📈 Supply-Borrow-Swap
**Strategy Flow:**
1. 💰 Supply collateral to Aave
2. 💸 Borrow asset
3. 🔄 Swap borrowed asset
4. 💰 Supply swapped asset back to Aave
> 📖 See `examples/ts/supply-borrow-swap.ts` for implementation.
---
## 💡 Best Practices
| Practice | Description | Status |
|----------|-------------|--------|
| 🛡️ **Slippage Protection** | Always set minimum output amounts | ✅ |
| ⛽ **Gas Costs** | Check gas costs for complex transactions | ✅ |
| 🔮 **TWAP Oracles** | Never rely on spot prices alone | ✅ |
| 🧪 **Test on Testnets** | Always test before mainnet | ✅ |
| ⚠️ **Error Handling** | Handle errors gracefully | ✅ |
| 📊 **Monitor Positions** | Track liquidation risks | ✅ |
| 🔐 **Use Permit2** | Save gas on approvals when possible | ✅ |
---
## 🎯 Next Steps
- 📖 Review [Security Best Practices](./SECURITY.md)
- 🔗 Check [Chain Configuration](./CHAIN_CONFIG.md) for adding new chains
- 📜 Explore example contracts in `contracts/examples/`
- 🧪 Run tests in `test/`
---
## 📚 Related Documentation
- 🔐 [Security Best Practices](./SECURITY.md)
- 🔗 [Chain Configuration](./CHAIN_CONFIG.md)
- 🧪 [Strategy Testing Guide](./STRATEGY_TESTING.md)
- ⚙️ [Environment Setup](./ENV_SETUP.md)

324
docs/SECURITY.md Normal file
View File

@@ -0,0 +1,324 @@
# 🔐 Security Best Practices
> Comprehensive security checklist for DeFi integration.
---
## 🛡️ General Security Principles
### 🔒 1. Access Control
- ✅ Use access control modifiers for sensitive functions
- ✅ Implement owner/admin roles properly
- ✅ Never hardcode private keys or mnemonics
- ✅ Use environment variables for sensitive data
### ✅ 2. Input Validation
- ✅ Validate all user inputs
- ✅ Check for zero addresses
- ✅ Validate amounts (no zero, no overflow)
- ✅ Check token decimals
### 🔄 3. Reentrancy Protection
- ✅ Use ReentrancyGuard for external calls
- ✅ Follow checks-effects-interactions pattern
- ✅ Be extra careful with flash loans
### ⚠️ 4. Error Handling
- ✅ Use require/assert appropriately
- ✅ Provide clear error messages
- ✅ Handle edge cases
- ✅ Test error conditions
---
## 🏦 Protocol-Specific Security
### 🏦 Aave v3
#### ⚡ Flash Loans
| Check | Status | Description |
|-------|--------|-------------|
| ⚠️ **Critical** | ✅ | Always repay flash loan + premium in `executeOperation` |
| ⚠️ **Critical** | ✅ | Verify `msg.sender == pool` in `executeOperation` |
| ⚠️ **Critical** | ✅ | Verify `initiator == address(this)` in `executeOperation` |
| ✅ | ✅ | Calculate premium correctly: `amount + premium` |
| ✅ | ✅ | Handle multi-asset flash loans carefully |
| ✅ | ✅ | Test repayment failure scenarios |
#### 💰 Interest Rate Modes
| Check | Status | Description |
|-------|--------|-------------|
| ⚠️ **Deprecated** | ✅ | Stable rate borrowing is deprecated in v3.3+ |
| ✅ | ✅ | Always use variable rate (mode = 2) for new integrations |
| ✅ | ✅ | Understand interest rate risks |
#### 🛡️ Collateral Management
- ✅ Check liquidation thresholds
- ✅ Monitor health factor
- ✅ Handle eMode/isolation mode restrictions
- ✅ Verify collateral can be enabled
### 🔄 Uniswap v3
#### 🛡️ Slippage Protection
| Check | Status | Description |
|-------|--------|-------------|
| ⚠️ **Critical** | ✅ | Always set `amountOutMinimum` with slippage tolerance |
| ✅ | ✅ | Use TWAP oracles, not spot prices |
| ✅ | ✅ | Account for price impact in large swaps |
| ✅ | ✅ | Consider using UniswapX for better execution |
#### 🔮 Oracle Security
| Check | Status | Description |
|-------|--------|-------------|
| ⚠️ **Critical** | ✅ | Never use spot prices for critical operations |
| ✅ | ✅ | Use TWAP with sufficient observation window |
| ✅ | ✅ | Verify observation cardinality |
| ✅ | ✅ | Protect against oracle manipulation |
#### 🔐 Permit2
- ✅ Verify signature validity
- ✅ Check expiration (deadline)
- ✅ Verify nonce (prevent replay)
- ✅ Protect against signature theft (verify spender)
### 🔗 Protocolink
#### ✅ Route Validation
- ✅ Verify all logics in the route
- ✅ Check token addresses
- ✅ Validate amounts
- ✅ Verify slippage settings
#### ⚡ Execution
- ✅ Check gas estimates
- ✅ Handle execution failures
- ✅ Verify router address
- ✅ Monitor transaction status
### 🏛️ Compound III
#### 💰 Borrowing
| Check | Status | Description |
|-------|--------|-------------|
| ⚠️ **Important** | ✅ | Understand base asset vs collateral |
| ✅ | ✅ | Check borrow limits |
| ✅ | ✅ | Monitor collateral ratio |
| ✅ | ✅ | Handle liquidation risks |
---
## 📜 Smart Contract Security
### ⚡ Flash Loan Receivers
```solidity
// ✅ Good: Verify caller and initiator
function executeOperation(
address asset,
uint256 amount,
uint256 premium,
address initiator,
bytes calldata params
) external override returns (bool) {
require(msg.sender == address(pool), "Invalid caller");
require(initiator == address(this), "Invalid initiator");
// Your logic here
// ✅ Good: Approve repayment
IERC20(asset).approve(address(pool), amount + premium);
return true;
}
```
### 🔄 Reentrancy Protection
```solidity
// ✅ Good: Use ReentrancyGuard
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract MyContract is ReentrancyGuard {
function withdraw() external nonReentrant {
// Safe withdrawal logic
}
}
```
### 🔒 Access Control
```solidity
// ✅ Good: Use access control
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyContract is Ownable {
function sensitiveFunction() external onlyOwner {
// Owner-only logic
}
}
```
---
## 🧪 Testing Security
### 🧪 Foundry Tests
- ✅ Test all edge cases
- ✅ Test error conditions
- ✅ Test reentrancy attacks
- ✅ Test flash loan scenarios
- ✅ Test with fork tests
- ✅ Test gas limits
### 📊 Test Coverage
- ✅ Unit tests for all functions
- ✅ Integration tests
- ✅ Fork tests on mainnet
- ✅ Fuzz tests for inputs
- ✅ Invariant tests
---
## 🚀 Deployment Security
### 🔍 Pre-Deployment
- ✅ Get professional security audit
- ✅ Review all dependencies
- ✅ Test on testnets extensively
- ✅ Verify all addresses
- ✅ Check contract sizes
### 🔐 Post-Deployment
- ✅ Monitor transactions
- ✅ Set up alerts
- ✅ Keep private keys secure
- ✅ Use multisig for admin functions
- ✅ Have an emergency pause mechanism
---
## ⚠️ Common Vulnerabilities
### 1. Reentrancy
**Bad**: External call before state update
```solidity
function withdraw() external {
msg.sender.call{value: balance}("");
balance = 0; // Too late!
}
```
**Good**: State update before external call
```solidity
function withdraw() external nonReentrant {
uint256 amount = balance;
balance = 0;
msg.sender.call{value: amount}("");
}
```
### 2. Integer Overflow
**Bad**: No overflow protection
```solidity
uint256 total = amount1 + amount2;
```
**Good**: Use SafeMath or Solidity 0.8+
```solidity
uint256 total = amount1 + amount2; // Safe in Solidity 0.8+
```
### 3. Access Control
**Bad**: No access control
```solidity
function withdraw() external {
// Anyone can call
}
```
**Good**: Proper access control
```solidity
function withdraw() external onlyOwner {
// Only owner can call
}
```
---
## 🔗 Resources
| Resource | Link |
|----------|------|
| OpenZeppelin Security | [docs.openzeppelin.com](https://docs.openzeppelin.com/contracts/security) |
| Consensys Best Practices | [consensys.github.io](https://consensys.github.io/smart-contract-best-practices/) |
| Aave Security | [docs.aave.com](https://docs.aave.com/developers/guides/security-best-practices) |
| Uniswap Security | [docs.uniswap.org](https://docs.uniswap.org/contracts/v4/concepts/security) |
---
## ✅ Security Audit Checklist
Before deploying to production:
- [ ] 🔍 Professional security audit completed
- [ ] 📦 All dependencies reviewed
- [ ] 🔒 Access control implemented
- [ ] 🔄 Reentrancy protection added
- [ ] ✅ Input validation implemented
- [ ] ⚠️ Error handling comprehensive
- [ ] 🧪 Tests cover edge cases
- [ ] ⛽ Gas optimization reviewed
- [ ] ⏸️ Emergency pause mechanism
- [ ] 👥 Multisig for admin functions
- [ ] 📊 Monitoring and alerts set up
---
## 🚨 Reporting Security Issues
If you discover a security vulnerability, please report it responsibly:
1.**DO NOT** open a public issue
2. 📧 Email security details to the maintainers
3. ⏰ Allow time for the issue to be addressed
4. 🔒 Follow responsible disclosure practices
---
## ⚠️ Disclaimer
This security guide is for educational purposes. Always get professional security audits before deploying to production.
---
## 📚 Related Documentation
- 📖 [Integration Guide](./INTEGRATION_GUIDE.md)
- 🔗 [Chain Configuration](./CHAIN_CONFIG.md)
- 🧪 [Strategy Testing Guide](./STRATEGY_TESTING.md)

587
docs/STRATEGY_TESTING.md Normal file
View File

@@ -0,0 +1,587 @@
# 🧪 DeFi Strategy Testing Framework
> A comprehensive CLI tool for testing DeFi strategies against local mainnet forks with support for success paths and controlled failure scenarios.
---
## 📋 Overview
The DeFi Strategy Testing Framework allows you to:
- ✅ Run **repeatable, deterministic simulations** of DeFi strategies on local mainnet forks
- 💥 Test both **success** and **failure** cases: liquidations, oracle shocks, cap limits, slippage, approvals, paused assets, etc.
- ✅ Provide **clear pass/fail assertions** (e.g., Aave Health Factor >= 1 after each step; exact token deltas; gas ceilings)
- 📊 Produce **auditable reports** (JSON + HTML) suitable for CI
- 🎲 **Fuzz test** strategies with parameterized inputs
- 🐋 **Automatically fund** test accounts via whale impersonation
---
## 🏗️ Architecture
```
/defi-strat-cli
/src/strat
/core # 🔧 Engine: fork control, scenario runner, assertions, reporting
- fork-orchestrator.ts # 🍴 Fork management (Anvil/Hardhat)
- scenario-runner.ts # ▶️ Executes scenarios step by step
- assertion-evaluator.ts # ✅ Evaluates assertions
- failure-injector.ts # 💥 Injects failure scenarios
- fuzzer.ts # 🎲 Fuzz testing with parameterized inputs
- whale-registry.ts # 🐋 Whale addresses for token funding
/adapters # 🔌 Protocol adapters
/aave-v3-adapter.ts # 🏦 Aave v3 operations
/uniswap-v3-adapter.ts # 🔄 Uniswap v3 swaps
/compound-v3-adapter.ts # 🏛️ Compound v3 operations
/erc20-adapter.ts # 💰 ERC20 token operations
/dsl # 📝 Strategy/Scenario schema + loader
- scenario-loader.ts # 📄 YAML/JSON parser
/reporters # 📊 Report generators
- json-reporter.ts # 📄 JSON reports
- html-reporter.ts # 🌐 HTML reports
- junit-reporter.ts # 🔧 JUnit XML for CI
/config # ⚙️ Configuration
- networks.ts # 🌐 Network configurations
- oracle-feeds.ts # 🔮 Oracle feed addresses
/scenarios # 📚 Example strategies
/aave
- leveraged-long.yml
- liquidation-drill.yml
/compound3
- supply-borrow.yml
```
---
## 🚀 Quick Start
### 📦 Installation
```bash
# Install dependencies
pnpm install
```
### ▶️ Run a Scenario
```bash
# Run a scenario
pnpm run strat run scenarios/aave/leveraged-long.yml
# Run with custom network
pnpm run strat run scenarios/aave/leveraged-long.yml --network base
# Generate reports
pnpm run strat run scenarios/aave/leveraged-long.yml \
--report out/run.json \
--html out/report.html \
--junit out/junit.xml
```
### 🧪 Test Script
For comprehensive testing with a real fork:
```bash
# Set your RPC URL
export MAINNET_RPC_URL=https://mainnet.infura.io/v3/YOUR_KEY
# Run test script
pnpm run strat:test
```
---
## 🖥️ CLI Commands
### 🍴 `fork up`
Start or attach to a fork instance.
```bash
pnpm run strat fork up --network mainnet --block 18500000
```
### ▶️ `run`
Run a scenario file.
```bash
pnpm run strat run <scenario-file> [options]
```
| Option | Description | Default |
|--------|-------------|---------|
| `--network <network>` | Network name or chain ID | `mainnet` |
| `--report <file>` | Output JSON report path | - |
| `--html <file>` | Output HTML report path | - |
| `--junit <file>` | Output JUnit XML report path | - |
| `--rpc <url>` | Custom RPC URL | - |
### 🎲 `fuzz`
Fuzz test a scenario with parameterized inputs.
```bash
pnpm run strat fuzz scenarios/aave/leveraged-long.yml --iters 100 --seed 42
```
| Option | Description | Default |
|--------|-------------|---------|
| `--iters <number>` | Number of iterations | `100` |
| `--seed <number>` | Random seed for reproducibility | - |
| `--report <file>` | Output JSON report path | - |
### 💥 `failures`
List available failure injection methods.
```bash
pnpm run strat failures [protocol]
```
### 📊 `compare`
Compare two run reports.
```bash
pnpm run strat compare out/run1.json out/run2.json
```
---
## 📝 Writing Scenarios
Scenarios are defined in YAML or JSON format:
```yaml
version: 1
network: mainnet
protocols: [aave-v3, uniswap-v3]
assumptions:
baseCurrency: USD
slippageBps: 30
minHealthFactor: 1.05
accounts:
trader:
funded:
- token: WETH
amount: "5"
steps:
- name: Approve WETH to Aave Pool
action: erc20.approve
args:
token: WETH
spender: aave-v3:Pool
amount: "max"
- name: Supply WETH
action: aave-v3.supply
args:
asset: WETH
amount: "5"
onBehalfOf: $accounts.trader
assert:
- aave-v3.healthFactor >= 1.5
- name: Borrow USDC
action: aave-v3.borrow
args:
asset: USDC
amount: "6000"
rateMode: variable
- name: Swap USDC->WETH
action: uniswap-v3.exactInputSingle
args:
tokenIn: USDC
tokenOut: WETH
fee: 500
amountIn: "3000"
- name: Oracle shock (-12% WETH)
action: failure.oracleShock
args:
feed: CHAINLINK_WETH_USD
pctDelta: -12
- name: Check HF still safe
action: assert
args:
expression: "aave-v3.healthFactor >= 1.05"
```
---
## 🔌 Supported Actions
### 🏦 Aave v3
| Action | Description | Status |
|--------|-------------|--------|
| `aave-v3.supply` | Supply assets to Aave | ✅ |
| `aave-v3.withdraw` | Withdraw assets from Aave | ✅ |
| `aave-v3.borrow` | Borrow assets from Aave | ✅ |
| `aave-v3.repay` | Repay borrowed assets | ✅ |
| `aave-v3.flashLoanSimple` | Execute a flash loan | ✅ |
**Views:**
- `aave-v3.healthFactor`: Get user health factor
- `aave-v3.userAccountData`: Get full user account data
### 🏛️ Compound v3
| Action | Description | Status |
|--------|-------------|--------|
| `compound-v3.supply` | Supply collateral to Compound v3 | ✅ |
| `compound-v3.withdraw` | Withdraw collateral or base asset | ✅ |
| `compound-v3.borrow` | Borrow base asset (withdraws base asset) | ✅ |
| `compound-v3.repay` | Repay debt (supplies base asset) | ✅ |
**Views:**
- `compound-v3.borrowBalance`: Get borrow balance
- `compound-v3.collateralBalance`: Get collateral balance for an asset
### 🔄 Uniswap v3
| Action | Description | Status |
|--------|-------------|--------|
| `uniswap-v3.exactInputSingle` | Execute an exact input swap | ✅ |
| `uniswap-v3.exactOutputSingle` | Execute an exact output swap | ✅ |
### 💰 ERC20
| Action | Description | Status |
|--------|-------------|--------|
| `erc20.approve` | Approve token spending | ✅ |
**Views:**
- `erc20.balanceOf`: Get token balance
### 💥 Failure Injection
| Action | Description | Status |
|--------|-------------|--------|
| `failure.oracleShock` | Inject an oracle price shock (attempts storage manipulation) | ✅ |
| `failure.timeTravel` | Advance time | ✅ |
| `failure.setTimestamp` | Set block timestamp | ✅ |
| `failure.liquidityShock` | Move liquidity | ✅ |
| `failure.setBaseFee` | Set gas price | ✅ |
| `failure.pauseReserve` | Pause a reserve (Aave) | ✅ |
| `failure.capExhaustion` | Simulate cap exhaustion | ✅ |
---
## ✅ Assertions
Assertions can be added to any step:
```yaml
steps:
- name: Check health factor
action: assert
args:
expression: "aave-v3.healthFactor >= 1.05"
```
### Supported Operators
| Operator | Description | Example |
|----------|-------------|---------|
| `>=` | Greater than or equal | `aave-v3.healthFactor >= 1.05` |
| `<=` | Less than or equal | `amount <= 1000` |
| `>` | Greater than | `balance > 0` |
| `<` | Less than | `gasUsed < 1000000` |
| `==` | Equal to | `status == "success"` |
| `!=` | Not equal to | `error != null` |
---
## 📊 Reports
### 📄 JSON Report
Machine-readable JSON format with full run details.
**Features:**
- ✅ Complete step-by-step execution log
- ✅ Assertion results
- ✅ Gas usage metrics
- ✅ Error messages and stack traces
- ✅ State deltas
### 🌐 HTML Report
Human-readable HTML report with:
- ✅ Run summary (pass/fail status, duration, gas)
- ✅ Step-by-step execution details
- ✅ Assertion results with visual indicators
- ✅ Gas usage charts
- ✅ Error messages with syntax highlighting
### 🔧 JUnit XML
CI-friendly XML format for integration with test runners.
**Features:**
- ✅ Compatible with Jenkins, GitLab CI, GitHub Actions
- ✅ Test suite and case structure
- ✅ Pass/fail status
- ✅ Error messages and stack traces
---
## 🍴 Fork Orchestration
The framework supports:
| Backend | Status | Features |
|---------|--------|----------|
| **Anvil** (Foundry) | ✅ | Fast, rich custom RPC methods |
| **Hardhat** | ✅ | Wider familiarity |
| **Tenderly** | 🚧 Coming soon | Optional remote simulation backend |
### 🎯 Fork Features
-**Snapshot/revert** - Fast test loops
- 🐋 **Account impersonation** - Fund/borrow from whales
-**Time travel** - Advance time, set timestamp
- 💾 **Storage manipulation** - Oracle overrides
-**Gas price control** - Test gas scenarios
---
## 🐋 Token Funding
The framework automatically funds test accounts via whale impersonation. Known whale addresses are maintained in the whale registry for common tokens.
### How It Works
1. 📋 Look up whale address from registry
2. 🎭 Impersonate whale on the fork
3. 💸 Transfer tokens to test account
4. ✅ Verify balance
### Adding New Whales
```typescript
// src/strat/core/whale-registry.ts
export const WHALE_REGISTRY: Record<number, Record<string, Address>> = {
1: {
YOUR_TOKEN: '0x...' as Address,
},
};
```
---
## 🔌 Protocol Adapters
### Adding a New Adapter
Implement the `ProtocolAdapter` interface:
```typescript
export interface ProtocolAdapter {
name: string;
discover(network: Network): Promise<RuntimeAddresses>;
actions: Record<string, (ctx: StepContext, args: any) => Promise<StepResult>>;
invariants?: Array<(ctx: StepContext) => Promise<void>>;
views?: Record<string, (ctx: ViewContext, args?: any) => Promise<any>>;
}
```
### Example Implementation
```typescript
export class MyProtocolAdapter implements ProtocolAdapter {
name = 'my-protocol';
async discover(network: Network): Promise<RuntimeAddresses> {
return {
contract: '0x...',
};
}
actions = {
myAction: async (ctx: StepContext, args: any): Promise<StepResult> => {
// Implement action
return { success: true };
},
};
views = {
myView: async (ctx: ViewContext): Promise<any> => {
// Implement view
return value;
},
};
}
```
---
## 💥 Failure Injection
### 🔮 Oracle Shocks
Inject price changes to test liquidation scenarios. The framework attempts to modify Chainlink aggregator storage:
```yaml
- name: Oracle shock
action: failure.oracleShock
args:
feed: CHAINLINK_WETH_USD
pctDelta: -12 # -12% price drop
# aggregatorAddress: 0x... # Optional, auto-resolved if not provided
```
> ⚠️ **Note:** Oracle storage manipulation requires precise slot calculation and may not work on all forks. The framework will attempt the manipulation and log warnings if it fails.
### ⏰ Time Travel
Advance time for interest accrual, maturity, etc.:
```yaml
- name: Advance time
action: failure.timeTravel
args:
seconds: 86400 # 1 day
```
### 💧 Liquidity Shocks
Move liquidity to test pool utilization:
```yaml
- name: Liquidity shock
action: failure.liquidityShock
args:
token: WETH
whale: 0x...
amount: "1000"
```
---
## 🎲 Fuzzing
Fuzz testing runs scenarios with parameterized inputs:
```bash
pnpm run strat fuzz scenarios/aave/leveraged-long.yml --iters 100 --seed 42
```
### What Gets Fuzzed
| Parameter | Variation | Description |
|-----------|-----------|-------------|
| Amounts | ±20% | Randomly vary token amounts |
| Oracle shocks | Within range | Vary oracle shock percentages |
| Fee tiers | Random selection | Test different fee tiers |
| Slippage | Variable | Vary slippage parameters |
### Features
- ✅ Each iteration runs on a fresh snapshot
- ✅ Failures don't affect subsequent runs
- ✅ Reproducible with seed parameter
- ✅ Detailed report for all iterations
---
## 🌐 Network Support
| Network | Chain ID | Status |
|---------|----------|--------|
| Ethereum Mainnet | 1 | ✅ |
| Base | 8453 | ✅ |
| Arbitrum One | 42161 | ✅ |
| Optimism | 10 | ✅ |
| Polygon | 137 | ✅ |
> 💡 Or use chain IDs directly: `--network 1` for mainnet.
---
## 🔐 Security & Safety
> ⚠️ **IMPORTANT**: This tool is for **local forks and simulations only**. Do **not** use real keys or send transactions on mainnet from this tool.
Testing "oracle shocks", liquidations, and admin toggles are **defensive simulations** to validate strategy resilience, **not** instructions for real-world exploitation.
---
## 📚 Examples
See the `scenarios/` directory for example scenarios:
| Scenario | Description | Path |
|----------|-------------|------|
| **Leveraged Long** | Leveraged long strategy with Aave and Uniswap | `aave/leveraged-long.yml` |
| **Liquidation Drill** | Test liquidation scenarios with oracle shocks | `aave/liquidation-drill.yml` |
| **Supply & Borrow** | Compound v3 supply and borrow example | `compound3/supply-borrow.yml` |
---
## 🔧 Troubleshooting
### ❌ Token Funding Fails
If token funding fails, check:
1. ✅ Whale address has sufficient balance on the fork
2. ✅ Fork supports account impersonation (Anvil)
3. ✅ RPC endpoint allows custom methods
### ❌ Oracle Shocks Don't Work
Oracle storage manipulation is complex and may fail if:
1. ❌ Storage slot calculation is incorrect
2. ❌ Fork doesn't support storage manipulation
3. ❌ Aggregator uses a different storage layout
> 💡 The framework will log warnings and continue - verify price changes manually if needed.
### ❌ Fork Connection Issues
If the fork fails to start:
1. ✅ Check RPC URL is correct and accessible
2. ✅ Verify network configuration
3. ✅ Check if fork block number is valid
---
## 🚀 Future Enhancements
- [ ] 🎯 Tenderly backend integration
- [ ] ⛽ Gas profiling & diffing
- [ ] 📊 Risk margin calculators
- [ ] 📈 HTML charts for HF over time
- [ ] 🔌 More protocol adapters (Maker, Curve, Balancer, etc.)
- [ ] ⚡ Parallel execution of scenarios
- [ ] 📝 Scenario templates and generators
---
## 🤝 Contributing
Contributions welcome! Please:
1. 🍴 Fork the repository
2. 🌿 Create a feature branch
3. ✏️ Make your changes
4. 🧪 Add tests
5. 📤 Submit a pull request
---
## 📄 License
MIT

View File

@@ -0,0 +1,299 @@
# 🎉 DeFi Strategy Testing Framework - Implementation Complete
## ✅ Completed Features
### 🔧 Core Engine
| Feature | Status | Description |
|---------|--------|-------------|
| Fork Orchestrator | ✅ | Anvil/Hardhat support |
| Scenario Runner | ✅ | Step-by-step execution |
| Assertion Evaluator | ✅ | Protocol view support |
| Failure Injector | ✅ | Oracle shocks, time travel, etc. |
| Fuzzer | ✅ | Parameterized inputs |
| Whale Registry | ✅ | Automatic token funding |
### 🔌 Protocol Adapters
#### 🏦 Aave v3 Adapter ✅
- ✅ Supply, withdraw, borrow, repay
- ✅ Flash loans (simple)
- ✅ Health factor monitoring
- ✅ User account data views
#### 🔄 Uniswap v3 Adapter ✅
- ✅ Exact input/output swaps
- ✅ Slippage handling
#### 🏛️ Compound v3 Adapter ✅
- ✅ Supply collateral
- ✅ Borrow base asset (withdraw)
- ✅ Repay debt (supply base asset)
- ✅ Borrow and collateral balance views
#### 💰 ERC20 Adapter ✅
- ✅ Token approvals
- ✅ Balance queries
### 💥 Failure Injection
| Feature | Status | Description |
|---------|--------|-------------|
| Oracle shocks | ✅ | Storage manipulation attempt |
| Time travel | ✅ | Advance time |
| Set block timestamp | ✅ | Set block timestamp |
| Liquidity shocks | ✅ | Move liquidity |
| Gas price manipulation | ✅ | Set gas price |
| Reserve pause simulation | ✅ | Pause reserves |
| Cap exhaustion simulation | ✅ | Simulate cap exhaustion |
### 📊 Reporting
| Format | Status | Description |
|--------|--------|-------------|
| JSON Reporter | ✅ | Machine-readable |
| HTML Reporter | ✅ | Human-readable |
| JUnit XML Reporter | ✅ | CI integration |
### 📝 DSL & Configuration
- ✅ YAML/JSON scenario loader
- ✅ Schema validation with Zod
- ✅ Network configuration
- ✅ Oracle feed registry
- ✅ Token metadata resolution
### 🖥️ CLI Commands
| Command | Status | Description |
|---------|--------|-------------|
| `fork up` | ✅ | Start/manage forks |
| `run` | ✅ | Execute scenarios |
| `fuzz` | ✅ | Fuzz test scenarios |
| `failures` | ✅ | List failure injections |
| `compare` | ✅ | Compare run reports |
| `assert` | ✅ | Re-check assertions (placeholder) |
### 📚 Example Scenarios
- ✅ Aave leveraged long strategy
- ✅ Aave liquidation drill
- ✅ Compound v3 supply/borrow
### 📖 Documentation
- ✅ Comprehensive strategy testing guide
- ✅ Scenario format documentation
- ✅ API documentation
- ✅ Examples and usage guides
### 🧪 Testing Infrastructure
- ✅ Test script for real fork testing
- ✅ Whale impersonation for token funding
- ✅ Snapshot/revert for fast iterations
---
## 🎯 Key Features
### 🐋 Automatic Token Funding
The framework automatically funds test accounts by:
1. 📋 Looking up whale addresses from the registry
2. 🎭 Impersonating whales on the fork
3. 💸 Transferring tokens to test accounts
4. ✅ Verifying balances
### 🔮 Enhanced Oracle Shocks
Oracle shocks attempt to modify Chainlink aggregator storage:
1. 🔍 Resolve aggregator address from feed name
2. 📊 Read current price and round ID
3. 🧮 Calculate new price based on percentage delta
4. 💾 Attempt to modify storage slot (with fallback warnings)
5. 📝 Log detailed information for verification
### 🎲 Fuzzing Support
Fuzzing runs scenarios with randomized parameters:
- ✅ Amounts vary by ±20%
- ✅ Oracle shock percentages vary within ranges
- ✅ Fee tiers randomly selected
- ✅ Slippage parameters varied
- ✅ Each iteration runs on a fresh snapshot
### 🔌 Multi-Protocol Support
The framework supports multiple protocols:
| Protocol | Features | Status |
|----------|----------|--------|
| Aave v3 | Lending/borrowing | ✅ |
| Uniswap v3 | Swaps | ✅ |
| Compound v3 | Lending/borrowing | ✅ |
| ERC20 tokens | Approvals, balances | ✅ |
---
## 📊 Usage Examples
### Basic Scenario Run
```bash
pnpm run strat run scenarios/aave/leveraged-long.yml
```
### Fuzz Testing
```bash
pnpm run strat fuzz scenarios/aave/leveraged-long.yml --iters 100 --seed 42
```
### With Reports
```bash
pnpm run strat run scenarios/aave/leveraged-long.yml \
--report out/run.json \
--html out/report.html \
--junit out/junit.xml
```
### Test Script
```bash
export MAINNET_RPC_URL=https://mainnet.infura.io/v3/YOUR_KEY
pnpm run strat:test
```
---
## 🔧 Technical Implementation
### 🍴 Fork Orchestration
- ✅ Supports Anvil (Foundry) and Hardhat
- ✅ Snapshot/revert for fast iterations
- ✅ Account impersonation for whale funding
- ✅ Storage manipulation for oracle overrides
- ✅ Time travel for interest accrual testing
### 🔌 Protocol Adapters
- ✅ Clean interface for adding new protocols
- ✅ Automatic address discovery
- ✅ View functions for assertions
- ✅ Invariant checking after each step
### 💥 Failure Injection
- ✅ Protocol-agnostic failures (oracle, time, gas)
- ✅ Protocol-specific failures (pause, caps)
- ✅ Storage manipulation where possible
- ✅ Fallback warnings when manipulation fails
### 🐋 Token Funding
- ✅ Whale registry for known addresses
- ✅ Automatic impersonation
- ✅ Transfer execution
- ✅ Balance verification
- ✅ Graceful degradation on failure
---
## 🚀 Next Steps (Future Enhancements)
While the core framework is complete, future enhancements could include:
### 🔌 More Protocol Adapters
- [ ] Maker DAO
- [ ] Curve
- [ ] Balancer
- [ ] Lido
### 💥 Enhanced Failure Injection
- [ ] More reliable oracle manipulation
- [ ] Protocol-specific failure modes
- [ ] Custom failure scenarios
### 🎲 Advanced Fuzzing
- [ ] Property-based testing
- [ ] Mutation testing
- [ ] Coverage-guided fuzzing
### 🔗 Integration
- [ ] Tenderly backend
- [ ] CI/CD integration
- [ ] Dashboard/UI
### 📊 Analysis
- [ ] Gas profiling
- [ ] Risk margin calculators
- [ ] Historical backtesting
---
## 📝 Notes
### 🔮 Oracle Manipulation
Oracle storage manipulation is complex and may not work on all forks. The framework attempts the manipulation and logs warnings if it fails. For production use, consider:
- ✅ Using mock oracles
- ✅ Deploying custom aggregators
- ✅ Using Tenderly's simulation capabilities
### 🐋 Token Funding
Token funding relies on:
- ✅ Whale addresses having sufficient balances
- ✅ Fork supporting account impersonation
- ✅ RPC endpoint allowing custom methods
If funding fails, accounts can be manually funded or alternative methods used.
### 🍴 Fork Requirements
For best results, use:
- ✅ Anvil (Foundry) for local forks
- ✅ RPC endpoints that support custom methods
- ✅ Sufficient block history for protocol state
---
## 🎉 Conclusion
The DeFi Strategy Testing Framework is now complete with:
- ✅ Full protocol adapter support (Aave, Uniswap, Compound)
- ✅ Comprehensive failure injection
- ✅ Fuzzing capabilities
- ✅ Automatic token funding
- ✅ Multiple report formats
- ✅ Complete documentation
The framework is ready for use in testing DeFi strategies against local mainnet forks with both success and failure scenarios.
---
## 📚 Related Documentation
- 📖 [Strategy Testing Guide](./STRATEGY_TESTING.md)
- ⚙️ [Environment Setup](./ENV_SETUP.md)
- 🔗 [Chain Configuration](./CHAIN_CONFIG.md)
- 🔐 [Security Best Practices](./SECURITY.md)