""" 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", }