Files
smom-dbis-138/docs/integration/DODO_PMM_INTEGRATION.md
defiQUG 2a4753eb2d feat: restore operator WIP — PMM JSON sync entrypoint, dotenv RPC trim + secrets, pool env alignment
- Resolve stash: merge load_deployment_env path with secure-secrets and CR/LF RPC strip
- create-pmm-full-mesh-chain138.sh delegates to sync-chain138-pmm-pools-from-json.sh
- env.additions.example: canonical PMM pool defaults (cUSDT/USDT per crosscheck)
- Include Chain138 scripts, official mirror deploy scaffolding, and prior staged changes

Made-with: Cursor
2026-03-27 19:02:30 -07:00

471 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DODO PMM Integration Documentation
**Date**: 2025-01-12
**Status**: Implementation Guide
**Purpose**: Integration with DODO Proactive Market Maker (PMM) for liquidity pools
---
## Overview
DODO PMM Integration enables liquidity pools between CompliantUSDT (cUSDT)/CompliantUSDC (cUSDC) and official USDT/USDC tokens. This provides:
- **Exchangeability**: Users can swap between compliant and official tokens
- **Price Stability**: PMM algorithm maintains 1:1 peg
- **Liquidity**: Efficient capital utilization
- **Arbitrage Opportunities**: Market-driven peg maintenance
---
## Architecture
### Contract: DODOPMMIntegration
**Location**: `contracts/dex/DODOPMMIntegration.sol`
**Purpose**:
- Create and manage DODO PMM pools
- Facilitate swaps between compliant and official tokens
- Manage liquidity provision
**Key Features**:
- Pool creation (cUSDT/USDT, cUSDC/USDC, cUSDT/cUSDC, and generic pairs)
- Liquidity management
- Swap execution
- Price discovery via PMM algorithm
### Public Pool Pairs (VAULT_SYSTEM_MASTER_TECHNICAL_PLAN §4)
The Master Plan specifies four **public** liquidity pool types for user routing and price discovery (not primary stabilization):
| Pair | Creation method | Notes |
|------|-----------------|--------|
| **cUSDT / cUSDC** | `createCUSDTCUSDCPool(lpFeeRate, initialPrice, k, isOpenTWAP)` | Dedicated function; swap via `swapCUSDTForUSDC` / `swapUSDCForCUSDT`. Register in DODOPMMProvider for getQuote/executeSwap. |
| **cUSDT / XAU** | `createPool(cUSDT, xauTokenAddress, ...)` | Use the Chain 138 XAU anchor token address (`cXAUC` or `cXAUT`) and the generic `createPool`. |
| **cUSDC / XAU** | `createPool(cUSDC, xauTokenAddress, ...)` | Same as above. |
| **cEURT / XAU** | `createPool(cEURTAddress, xauTokenAddress, ...)` | Requires `cEURT` and a Chain 138 XAU anchor token (`cXAUC` or `cXAUT`). |
For cUSDT/XAU, cUSDC/XAU, and cEURT/XAU: use the deployed Chain 138 XAU anchor token (`cXAUC` at `0x290E52a8819A4fbD0714E517225429aA2B70EC6b` or `cXAUT` at `0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E`), then call `createPool(baseToken, quoteToken, lpFeeRate, initialPrice, k, isOpenTWAP)` with `POOL_MANAGER_ROLE`. **Unit:** 1 full XAU token = **1 troy ounce** of gold (`10^6` base units with 6 decimals). Public pools serve user routing, price discovery, and flash loan access; they do not serve as the primary stabilization engine (see Master Plan private mesh).
---
## DODO PMM Overview
### Proactive Market Maker (PMM)
DODO's PMM algorithm:
- Uses external price oracles (TWAP)
- Maintains price stability through automated market making
- More capital efficient than traditional AMMs
- Lower slippage for stablecoin pairs
### Pool Types
**DODO Vending Machine (DVM)**:
- Most common for custom pairs
- Supports single-sided liquidity provision
- Better for stablecoin pairs
**Key Parameters**:
- `i`: Initial price (1e18 = $1 for stablecoins)
- `k`: Slippage factor (lower = less slippage, 0.5e18 recommended)
- `lpFeeRate`: LP fee in basis points (3 = 0.03%)
- `isOpenTWAP`: Enable time-weighted average price oracle
---
## Deployment
### Prerequisites
1. **DODO Contracts** (check DODO docs for chain-specific addresses):
- DODO Vending Machine Factory
- DODO Approve (optional, for gas optimization)
2. **Token Addresses**:
- Official USDT/USDC (on target chain)
- Compliant cUSDT/cUSDC (on Chain 138)
3. **Network**: Deploy on chain where official tokens exist
### Deployment Steps
#### Step 1: Set Environment Variables
```bash
# In .env file
PRIVATE_KEY=0x...
RPC_URL=https://...
# DODO contracts (example for Ethereum Mainnet - check DODO docs)
DODO_VENDING_MACHINE_ADDRESS=0x... # DODO Vending Machine Factory
DODO_APPROVE_ADDRESS=0x... # Optional
# Official tokens on Chain 138 (local quote-side mirror stables)
OFFICIAL_USDT_ADDRESS=0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1
OFFICIAL_USDC_ADDRESS=0x71D6687F38b93CCad569Fa6352c876eea967201b
# Compliant tokens
COMPLIANT_USDT_ADDRESS=0x93E66202A11B1772E55407B32B44e5Cd8eda7f22
COMPLIANT_USDC_ADDRESS=0xf22258f57794CC8E06237084b353Ab30fFfa640b
# Admin
DODO_INTEGRATION_ADMIN=0x...
```
#### Step 2: Deploy Contract
```bash
cd smom-dbis-138
forge script script/dex/DeployDODOPMMIntegration.s.sol:DeployDODOPMMIntegration \
--rpc-url $RPC_URL \
--broadcast \
--legacy \
--gas-price 30000000000 \
--via-ir \
-vv
# Save deployed address
export DODO_PMM_INTEGRATION_ADDRESS=<deployed_address>
```
---
## Pool Creation
### Create cUSDT/USDT Pool
```bash
# Pool parameters
LP_FEE_RATE=3 # 0.03% = 3 basis points
INITIAL_PRICE=1000000000000000000 # 1e18 = $1
K_FACTOR=500000000000000000 # 0.5e18 = 50% slippage factor
ENABLE_TWAP=true # Enable TWAP oracle
cast send $DODO_PMM_INTEGRATION_ADDRESS \
"createCUSDTUSDTPool(uint256,uint256,uint256,bool)" \
$LP_FEE_RATE \
$INITIAL_PRICE \
$K_FACTOR \
$ENABLE_TWAP \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--gas-price 30000000000 \
--legacy \
-vv
# Get pool address
POOL_ADDRESS=$(cast call $DODO_PMM_INTEGRATION_ADDRESS \
"pools(address,address)" \
$COMPLIANT_USDT_ADDRESS \
$OFFICIAL_USDT_ADDRESS \
--rpc-url $RPC_URL | cast --to-addr)
```
### Create cUSDC/USDC Pool
```bash
cast send $DODO_PMM_INTEGRATION_ADDRESS \
"createCUSDCUSDCPool(uint256,uint256,uint256,bool)" \
$LP_FEE_RATE \
$INITIAL_PRICE \
$K_FACTOR \
$ENABLE_TWAP \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--gas-price 30000000000 \
--legacy \
-vv
```
---
## Liquidity Provision
### Add Liquidity to Pool
```bash
# Parameters
POOL_ADDRESS=0x... # Pool address from creation
BASE_AMOUNT=1000000000000 # Amount of base token (cUSDT/cUSDC)
QUOTE_AMOUNT=1000000000000 # Amount of quote token (USDT/USDC)
# 1. Approve tokens to integration contract
cast send $COMPLIANT_USDT_ADDRESS \
"approve(address,uint256)" \
$DODO_PMM_INTEGRATION_ADDRESS \
$BASE_AMOUNT \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--gas-price 30000000000 \
--legacy
cast send $OFFICIAL_USDT_ADDRESS \
"approve(address,uint256)" \
$DODO_PMM_INTEGRATION_ADDRESS \
$QUOTE_AMOUNT \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--gas-price 30000000000 \
--legacy
# 2. Add liquidity
cast send $DODO_PMM_INTEGRATION_ADDRESS \
"addLiquidity(address,uint256,uint256)" \
$POOL_ADDRESS \
$BASE_AMOUNT \
$QUOTE_AMOUNT \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--gas-price 30000000000 \
--legacy \
-vv
```
---
## Swapping
### Swap cUSDT → USDT
```bash
AMOUNT_IN=1000000000000 # 1,000,000 cUSDT (6 decimals)
MIN_AMOUNT_OUT=999000000000 # Minimum USDT to receive (slippage protection)
# 1. Approve cUSDT
cast send $COMPLIANT_USDT_ADDRESS \
"approve(address,uint256)" \
$DODO_PMM_INTEGRATION_ADDRESS \
$AMOUNT_IN \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--gas-price 30000000000 \
--legacy
# 2. Execute swap
cast send $DODO_PMM_INTEGRATION_ADDRESS \
"swapCUSDTForUSDT(address,uint256,uint256)" \
$POOL_ADDRESS \
$AMOUNT_IN \
$MIN_AMOUNT_OUT \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--gas-price 30000000000 \
--legacy \
-vv
```
### Swap USDT → cUSDT
```bash
# Similar process, using swapUSDTForCUSDT()
cast send $DODO_PMM_INTEGRATION_ADDRESS \
"swapUSDTForCUSDT(address,uint256,uint256)" \
$POOL_ADDRESS \
$AMOUNT_IN \
$MIN_AMOUNT_OUT \
--rpc-url $RPC_URL \
--private-key $PRIVATE_KEY \
--gas-price 30000000000 \
--legacy \
-vv
```
---
## Oracle and Reporting
### Optional ReserveSystem (oracle-backed mid price)
PMM pool price can be driven by the **ReserveSystem** when base/quote tokens are registered there. This gives reporting and off-chain services an oracle-backed price when available.
1. **Set ReserveSystem** (admin only):
```bash
cast send $DODO_PMM_INTEGRATION_ADDRESS \
"setReserveSystem(address)" \
$RESERVE_SYSTEM_ADDRESS \
--rpc-url $RPC_URL --private-key $PRIVATE_KEY
```
Use `address(0)` to disable and fall back to pool `getMidPrice()` only.
2. **getPoolPriceOrOracle(pool)** returns: oracle price (via `reserveSystem.getConversionPrice(baseToken, quoteToken)`) if ReserveSystem is set and returns a valid price; otherwise pool `getMidPrice()`.
3. **DODOPMMProvider** uses `getPoolPriceOrOracle` for quotes, so liquidity provider quotes prefer the oracle when configured.
### Reporting API and pool indexer
The **token-aggregation** service indexes PMM pools for `/report/all`, `/report/coingecko`, and `/report/cross-chain` when **CHAIN_138_DODO_PMM_INTEGRATION** is set.
- Set in token-aggregation `.env`: `CHAIN_138_DODO_PMM_INTEGRATION=<DODOPMMIntegration address>`.
- The pool indexer calls `getAllPools()`, then for each pool `getPoolConfig`, `getPoolReserves`, and `getPoolPriceOrOracle` to compute TVL and persist pools to the DB.
- Ensure the indexer runs for Chain 138 (cron or on-demand) so report endpoints include PMM pools.
See also: [PRICE_FEED_SETUP.md](PRICE_FEED_SETUP.md) for ReserveSystem/OraclePriceFeed setup; [ORACLE_AND_KEEPER_CHAIN138.md](ORACLE_AND_KEEPER_CHAIN138.md) for ORACLE_AGGREGATOR/ORACLE_PROXY and keeper flows on Chain 138.
### PMM price for vault / reporting
**PMMPriceProvider** (`contracts/vault/adapters/PMMPriceProvider.sol`) exposes `getPrice(asset, quoteToken)` using DODOPMMIntegrations `getPoolPriceOrOracle`. Use it for vault collateral valuation (e.g. cUSDT/cUSDC in USD terms) or off-chain reporting when the asset is a PMM pair token. Deploy with the DODOPMMIntegration address; see [Vault IMPLEMENTATION_SUMMARY](../vault/IMPLEMENTATION_SUMMARY.md#gru-smart-vault-and-pmm-integration).
---
## Query Functions
### Get Pool Price (oracle if configured)
```bash
# Prefer oracle when ReserveSystem is set
cast call $DODO_PMM_INTEGRATION_ADDRESS \
"getPoolPriceOrOracle(address)" \
$POOL_ADDRESS \
--rpc-url $RPC_URL
# Pool mid only (no oracle)
cast call $DODO_PMM_INTEGRATION_ADDRESS \
"getPoolPrice(address)" \
$POOL_ADDRESS \
--rpc-url $RPC_URL
# Returns: price in 1e18 format (1000000000000000000 = $1)
```
### Get Pool Reserves
```bash
cast call $DODO_PMM_INTEGRATION_ADDRESS \
"getPoolReserves(address)" \
$POOL_ADDRESS \
--rpc-url $RPC_URL
# Returns: (baseReserve, quoteReserve)
```
### Get Pool Configuration
```bash
cast call $DODO_PMM_INTEGRATION_ADDRESS \
"getPoolConfig(address)" \
$POOL_ADDRESS \
--rpc-url $RPC_URL
# Returns: PoolConfig struct with all parameters
```
### Get All Pools
```bash
cast call $DODO_PMM_INTEGRATION_ADDRESS \
"getAllPools()" \
--rpc-url $RPC_URL
# Returns: Array of all pool addresses
```
---
## Pool Parameters Guide
### Initial Price (`i`)
- **Value**: `1000000000000000000` (1e18)
- **Meaning**: $1 for stablecoin pairs
- **Adjustment**: Can set different initial price if needed
### K Factor (`k`)
- **Range**: 0 to 1e18
- **Recommended**: `500000000000000000` (0.5e18 = 50%)
- **Lower k**: Less slippage, more capital intensive
- **Higher k**: More slippage, less capital intensive
- **For stablecoins**: Lower k (0.3-0.5) recommended
### LP Fee Rate
- **Unit**: Basis points (100 = 1%)
- **Recommended**: 3-10 basis points (0.03% - 0.1%)
- **Lower fee**: More attractive for traders
- **Higher fee**: More revenue for LPs
### TWAP Oracle
- **Purpose**: Price discovery and stability
- **Recommended**: Enable for stablecoin pairs
- **Benefit**: Reduces price manipulation
---
## Integration Workflow
### Phase 1: Setup
1. Deploy DODOPMMIntegration contract
2. Create pools (cUSDT/USDT, cUSDC/USDC)
3. Configure pool parameters
### Phase 2: Seed Liquidity
1. Approve tokens to integration contract
2. Add initial liquidity to pools
3. Monitor pool reserves and prices
### Phase 3: Enable Trading
1. Open pools for public trading
2. Monitor swap volumes
3. Adjust parameters if needed
### Phase 4: Maintenance
1. Monitor pool health
2. Add/remove liquidity as needed
3. Update parameters for optimization
---
## Best Practices
1. **Liquidity Depth**: Maintain sufficient liquidity for expected volume
2. **Price Monitoring**: Monitor pool prices vs. 1:1 peg
3. **Arbitrage**: Allow arbitrageurs to maintain peg
4. **Slippage Protection**: Use appropriate slippage tolerances
5. **Gas Optimization**: Use DODO Approve for batch operations
6. **Security**: Audit contracts before mainnet deployment
---
## Troubleshooting
### Pool Creation Fails
- Check DODO Vending Machine address is correct
- Verify token addresses are valid
- Ensure sufficient gas
### Swaps Failing
- Check pool has sufficient liquidity
- Verify slippage tolerance is appropriate
- Check token approvals
### Price Deviation
- Check pool reserves are balanced
- Monitor for large trades
- Consider adding/removing liquidity
---
## Example Setup Script
See `scripts/setup-dodo-pools.sh` for automated pool creation and configuration.
---
## Next Steps
1. Deploy integration contract
2. Create pools with optimal parameters
3. Seed initial liquidity
4. Enable trading
5. Monitor and optimize