muthuk1's picture
Add config/constants.py
c3f6357 verified
Raw
History Blame
13.7 kB
"""
Dynamic RWA Yield Router β€” Configuration & Constants
=====================================================
All contract addresses, ABIs, chain configuration, and protocol parameters
for the Mantle L2 ecosystem (Chain ID 5000).
"""
import os
from dataclasses import dataclass, field
from typing import Dict, List, Optional
from enum import Enum
# ─────────────────────────── Chain Config ───────────────────────────
MANTLE_CHAIN_ID = 5000
MANTLE_RPC_URL = os.getenv("MANTLE_RPC_URL", "https://rpc.mantle.xyz")
MANTLE_WSS_URL = os.getenv("MANTLE_WSS_URL", "wss://ws.mantle.xyz")
MANTLE_EXPLORER = "https://explorer.mantle.xyz"
MANTLE_BLOCK_TIME_SECONDS = 2 # Mantle L2 ~2s blocks
# ─────────────────────────── Token Addresses (Mantle Mainnet) ───────
class Tokens:
"""Core token contract addresses on Mantle L2."""
# Stablecoins
USDC = "0x09Bc4E0D864854c6aFB6eB9A9cdF58aC190D0dF9"
USDT = "0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE"
# Native / Wrapped
WMNT = "0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8"
WETH = "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111"
# RWA Assets β€” Core Portfolio
USDY = "0x5bE26527e817998A7206475496fDE1E68957c5A6" # Ondo USDY (tokenized T-bills, ~4.25% APY)
METH = "0xcDA86A272531e8640cD7F1a92c01839911B90bb0" # Mantle Staked ETH (~3-5% APY)
CMETH = "0xE6829d9a7eE3040e1276Fa75293Bde931859e8fD" # Mantle Restaked ETH (cmETH)
# MI4 β€” Mantle Index Four (multi-chain, primary on Avalanche)
# On Mantle, MI4 exposure may be achieved via bridged tokens or Securitize portal
MI4_AVALANCHE = "0xe87db19a4a45a804f9b6e8038777c9a0ffbc5808"
MI4_PROXY = None # Set via env if bridged to Mantle
# Fluxion xStocks RWA tokens (on Mantle)
XAAPL = "0x3E6f0A37E795dA0304a7fC400f4CF6D8D028e1Ee"
XGOOG = "0x98a4eaB8B6CFE76EB8e36FcB5a0F09E2E4B62c2b"
XAMZN = "0x3607c534e9Ae5B4f1e968d9E7480e9D8a5f22eAa"
XTSLA = "0x5762E9828C8EEF98Ae08C7F8eB2C53C3dF6C4c2C"
XSPY = "0x5D9D2F2d8b8E7B5C0E5d6A4b0E7F1c2A3D4E5F6A" # Placeholder
# ─────────────────────────── DEX Router Addresses ───────────────────
class DEXRouters:
"""DEX router contracts on Mantle."""
FLUXION_SWAP_ROUTER = "0x5628a59df0ecac3f3171f877a94beb26ba6dfaa0"
AGNI_SWAP_ROUTER = "0x319B69888b0d11cEC22caA5034e25FfFBDc88421"
MERCHANT_MOE_ROUTER = "0xeaEE7EE68874218c3558b40063c42B82D3E7232a"
# Fluxion V3 (Uni V3 fork) β€” primary for RWA pairs
FLUXION_FACTORY = "0x5CA14E40bB7Bc70A3c2e672D5F43e5B8cE48ec68"
FLUXION_QUOTER = "0x64B421eE1a1Ed22ed2288B4e3e15Dd9bD5AC5B68"
# ─────────────────────────── Lending Protocol Addresses ─────────────
class LendingProtocols:
"""Lending/yield protocol contracts on Mantle."""
# Aave V3 (Lendle fork on Mantle)
AAVE_V3_POOL = "0x458F293454fE0d67EC0655f3672301301DD51422"
AAVE_V3_POOL_DATA_PROVIDER = "0x5DA14e30e92E20C9B4Fe3e22c2B499D7EA0E8b02"
# INIT Capital
INIT_CORE = "0x972BcD3960c17E5e1f2B98713c2B1A1E1eE1e2D3" # Verify on deploy
# Pendle (yield tokenization)
PENDLE_ROUTER = "0x00000000005BBB0EF59571E58418F9a4357b68A0"
# ─────────────────────────── Minimal ABIs ───────────────────────────
ERC20_ABI = [
{"constant": True, "inputs": [], "name": "name", "outputs": [{"name": "", "type": "string"}], "type": "function"},
{"constant": True, "inputs": [], "name": "symbol", "outputs": [{"name": "", "type": "string"}], "type": "function"},
{"constant": True, "inputs": [], "name": "decimals", "outputs": [{"name": "", "type": "uint8"}], "type": "function"},
{"constant": True, "inputs": [], "name": "totalSupply", "outputs": [{"name": "", "type": "uint256"}], "type": "function"},
{"constant": True, "inputs": [{"name": "_owner", "type": "address"}], "name": "balanceOf", "outputs": [{"name": "balance", "type": "uint256"}], "type": "function"},
{"constant": False, "inputs": [{"name": "_spender", "type": "address"}, {"name": "_value", "type": "uint256"}], "name": "approve", "outputs": [{"name": "", "type": "bool"}], "type": "function"},
{"constant": True, "inputs": [{"name": "_owner", "type": "address"}, {"name": "_spender", "type": "address"}], "name": "allowance", "outputs": [{"name": "", "type": "uint256"}], "type": "function"},
{"constant": False, "inputs": [{"name": "_to", "type": "address"}, {"name": "_value", "type": "uint256"}], "name": "transfer", "outputs": [{"name": "", "type": "bool"}], "type": "function"},
]
# Uniswap V3 SwapRouter (Fluxion/Agni compatible)
SWAP_ROUTER_ABI = [
{
"inputs": [
{
"components": [
{"name": "tokenIn", "type": "address"},
{"name": "tokenOut", "type": "address"},
{"name": "fee", "type": "uint24"},
{"name": "recipient", "type": "address"},
{"name": "deadline", "type": "uint256"},
{"name": "amountIn", "type": "uint256"},
{"name": "amountOutMinimum", "type": "uint256"},
{"name": "sqrtPriceLimitX96", "type": "uint160"},
],
"name": "params",
"type": "tuple",
}
],
"name": "exactInputSingle",
"outputs": [{"name": "amountOut", "type": "uint256"}],
"type": "function",
},
{
"inputs": [
{
"components": [
{"name": "path", "type": "bytes"},
{"name": "recipient", "type": "address"},
{"name": "deadline", "type": "uint256"},
{"name": "amountIn", "type": "uint256"},
{"name": "amountOutMinimum", "type": "uint256"},
],
"name": "params",
"type": "tuple",
}
],
"name": "exactInput",
"outputs": [{"name": "amountOut", "type": "uint256"}],
"type": "function",
},
]
# Aave V3 Pool β€” supply/withdraw
AAVE_POOL_ABI = [
{
"inputs": [
{"name": "asset", "type": "address"},
{"name": "amount", "type": "uint256"},
{"name": "onBehalfOf", "type": "address"},
{"name": "referralCode", "type": "uint16"},
],
"name": "supply",
"outputs": [],
"type": "function",
},
{
"inputs": [
{"name": "asset", "type": "address"},
{"name": "amount", "type": "uint256"},
{"name": "to", "type": "address"},
],
"name": "withdraw",
"outputs": [{"name": "", "type": "uint256"}],
"type": "function",
},
{
"inputs": [{"name": "asset", "type": "address"}],
"name": "getReserveData",
"outputs": [
{
"components": [
{"name": "configuration", "type": "uint256"},
{"name": "liquidityIndex", "type": "uint128"},
{"name": "currentLiquidityRate", "type": "uint128"},
{"name": "variableBorrowIndex", "type": "uint128"},
{"name": "currentVariableBorrowRate", "type": "uint128"},
{"name": "currentStableBorrowRate", "type": "uint128"},
{"name": "lastUpdateTimestamp", "type": "uint40"},
{"name": "id", "type": "uint16"},
{"name": "aTokenAddress", "type": "address"},
{"name": "stableDebtTokenAddress", "type": "address"},
{"name": "variableDebtTokenAddress", "type": "address"},
{"name": "interestRateStrategyAddress", "type": "address"},
{"name": "accruedToTreasury", "type": "uint128"},
{"name": "unbacked", "type": "uint128"},
{"name": "isolationModeTotalDebt", "type": "uint128"},
],
"name": "",
"type": "tuple",
}
],
"type": "function",
},
]
# mETH staking β€” read staking yield
METH_STAKING_ABI = [
{"constant": True, "inputs": [], "name": "mETHToETH", "outputs": [{"name": "", "type": "uint256"}], "type": "function"},
{"constant": True, "inputs": [], "name": "totalControlled", "outputs": [{"name": "", "type": "uint256"}], "type": "function"},
{"constant": True, "inputs": [], "name": "exchangeRateUpdatedAt", "outputs": [{"name": "", "type": "uint256"}], "type": "function"},
]
# ─────────────────────────── Portfolio Parameters ───────────────────
@dataclass
class PortfolioConfig:
"""Default portfolio allocation parameters."""
# Asset universe
assets: List[str] = field(default_factory=lambda: ["USDY", "mETH", "MI4"])
# Target yield (annualized)
min_target_apy: float = 3.5 # minimum acceptable APY %
max_target_apy: float = 12.0 # aspirational max
# Risk constraints
max_single_asset_weight: float = 0.60 # no single asset > 60%
min_single_asset_weight: float = 0.05 # minimum 5% in each active asset
max_drawdown_pct: float = 0.10 # 10% max drawdown trigger
# Rebalancing
rebalance_threshold_pct: float = 0.05 # rebalance when drift > 5%
min_rebalance_interval_hours: int = 4 # no more frequent than 4h
max_rebalance_interval_hours: int = 168 # at least weekly
# Gas budget
max_gas_per_rebalance_usd: float = 5.0 # Mantle gas is cheap (~$0.01-0.10/tx)
# Slippage
max_slippage_bps: int = 50 # 0.5% max slippage
@dataclass
class RiskConfig:
"""Risk management parameters."""
# Depeg detection thresholds
usdy_depeg_threshold: float = 0.005 # USDY/USD deviation > 0.5%
meth_depeg_threshold: float = 0.02 # mETH/ETH deviation > 2%
# Circuit breakers
circuit_breaker_cooldown_hours: int = 24
emergency_exit_to: str = "USDC" # flee to stablecoin on emergency
# Smart contract risk scores (0-1, higher = riskier)
protocol_risk_scores: Dict[str, float] = field(default_factory=lambda: {
"USDY": 0.15, # Ondo β€” audited, regulated, low risk
"mETH": 0.25, # Mantle LSP β€” battle-tested but smart contract risk
"MI4": 0.30, # Securitize β€” newer product, moderate risk
"Aave": 0.10, # Heavily audited
"Fluxion": 0.35, # Newer DEX, higher risk
})
# Volatility lookback
volatility_window_days: int = 30
correlation_window_days: int = 90
@dataclass
class RLConfig:
"""Reinforcement Learning hyperparameters."""
# PPO parameters
learning_rate: float = 3e-4
gamma: float = 0.99 # discount factor
gae_lambda: float = 0.95 # GAE lambda
clip_range: float = 0.2 # PPO clip
entropy_coef: float = 0.01 # exploration bonus
value_coef: float = 0.5
max_grad_norm: float = 0.5
# Training
n_steps: int = 2048
batch_size: int = 64
n_epochs: int = 10
total_timesteps: int = 1_000_000
# State space dimension
state_dim: int = 15 # yield rates, prices, volatilities, portfolio weights, macro
action_dim: int = 3 # weights for [USDY, mETH, MI4]
# Environment
episode_length_days: int = 30
reward_scaling: float = 100.0 # scale small yield differences
# ─────────────────────────── API Endpoints ──────────────────────────
class APIEndpoints:
"""External data source endpoints."""
DEFILLAMA_YIELDS = "https://yields.llama.fi/pools"
DEFILLAMA_PROTOCOL = "https://api.llama.fi/protocol/{protocol}"
DEFILLAMA_TVL = "https://api.llama.fi/tvl/{protocol}"
COINGECKO_PRICE = "https://api.coingecko.com/api/v3/simple/price"
COINGECKO_HISTORY = "https://api.coingecko.com/api/v3/coins/{coin_id}/market_chart"
BYBIT_TICKER = "https://api.bybit.com/v5/market/tickers"
BYBIT_KLINE = "https://api.bybit.com/v5/market/kline"
# Federal Reserve data
FRED_API = "https://api.stlouisfed.org/fred/series/observations"
# Mantle-specific
MANTLE_SUBGRAPH = "https://subgraph.mantle.xyz/subgraphs/name/{name}"
# ─────────────────────────── Logging Config ─────────────────────────
LOG_FORMAT = "%(asctime)s | %(name)-20s | %(levelname)-7s | %(message)s"
LOG_DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
# ─────────────────────────── ERC-8004 Agent Identity ────────────────
ERC8004_CAPABILITIES = [
"yield_optimization",
"portfolio_rebalancing",
"risk_assessment",
"market_analysis",
"strategy_reporting",
]
AGENT_METADATA = {
"name": "Dynamic RWA Yield Router",
"version": "1.0.0",
"description": "Autonomous AI agent for yield-optimized RWA portfolio management on Mantle",
"chain_id": MANTLE_CHAIN_ID,
"supported_assets": ["USDY", "mETH", "MI4"],
"risk_framework": "risk-parity-adaptive",
"rl_algorithm": "PPO",
}