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
This commit is contained in:
defiQUG
2026-03-27 19:02:30 -07:00
parent c6e7bad15e
commit 2a4753eb2d
200 changed files with 5987 additions and 913 deletions

View File

@@ -12,6 +12,7 @@ import "./interfaces/IAggregationRouter.sol";
import "./interfaces/IDodoexRouter.sol";
import "./interfaces/IBalancerVault.sol";
import "./interfaces/IWETH.sol";
import "../../liquidity/interfaces/ILiquidityProvider.sol";
/**
* @title EnhancedSwapRouter
@@ -67,6 +68,7 @@ contract EnhancedSwapRouter is AccessControl, ReentrancyGuard {
// Dodoex PMM pool addresses (tokenIn => tokenOut => PMM pool address)
mapping(address => mapping(address => address)) public dodoPoolAddresses;
address public dodoLiquidityProvider;
/// @dev Uniswap V3 Quoter for on-chain quotes; set via setUniswapQuoter when deployed on 138/651940
address public uniswapQuoter;
@@ -91,6 +93,7 @@ contract EnhancedSwapRouter is AccessControl, ReentrancyGuard {
error ProviderDisabled();
error InsufficientOutput();
error InvalidRoutingConfig();
error DodoRouteNotConfigured();
/**
* @notice Constructor
@@ -324,6 +327,15 @@ contract EnhancedSwapRouter is AccessControl, ReentrancyGuard {
dodoPoolAddresses[tokenIn][tokenOut] = poolAddress;
}
/**
* @notice Set DODO liquidity provider implementation for environments that execute
* swaps via a local provider/integration instead of an external Dodoex router.
* @param provider Address of ILiquidityProvider-compatible contract
*/
function setDodoLiquidityProvider(address provider) external onlyRole(ROUTING_MANAGER_ROLE) {
dodoLiquidityProvider = provider;
}
/**
* @notice Set Uniswap V3 Quoter address for on-chain quotes
* @param _quoter Quoter contract address (address(0) to use 0.5% slippage estimate)
@@ -349,9 +361,23 @@ contract EnhancedSwapRouter is AccessControl, ReentrancyGuard {
if (amountIn == 0) revert ZeroAmount();
if (tokenIn == address(0) || tokenOut == address(0)) revert ZeroAddress();
address pool = dodoPoolAddresses[tokenIn][tokenOut];
require(pool != address(0), "EnhancedSwapRouter: Dodoex pool not configured");
if (!_hasDodoRoute(tokenIn, tokenOut, pool)) revert DodoRouteNotConfigured();
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
if (dodoLiquidityProvider != address(0)) {
IERC20(tokenIn).approve(dodoLiquidityProvider, amountIn);
amountOut = ILiquidityProvider(dodoLiquidityProvider).executeSwap(
tokenIn,
tokenOut,
amountIn,
amountOutMin
);
require(amountOut >= amountOutMin, "EnhancedSwapRouter: insufficient output");
IERC20(tokenOut).safeTransfer(msg.sender, amountOut);
return amountOut;
}
IERC20(tokenIn).approve(dodoexRouter, amountIn);
address[] memory dodoPairs = new address[](1);
@@ -476,7 +502,18 @@ contract EnhancedSwapRouter is AccessControl, ReentrancyGuard {
uint256 amountOutMin
) internal returns (uint256) {
address pool = dodoPoolAddresses[weth][stablecoinToken];
require(pool != address(0), "EnhancedSwapRouter: Dodoex pool not configured");
if (!_hasDodoRoute(weth, stablecoinToken, pool)) revert DodoRouteNotConfigured();
if (dodoLiquidityProvider != address(0)) {
IERC20 wethTokenViaProvider = IERC20(weth);
wethTokenViaProvider.approve(dodoLiquidityProvider, amountIn);
return ILiquidityProvider(dodoLiquidityProvider).executeSwap(
weth,
stablecoinToken,
amountIn,
amountOutMin
);
}
IERC20 wethToken = IERC20(weth);
wethToken.approve(dodoexRouter, amountIn);
@@ -605,9 +642,30 @@ contract EnhancedSwapRouter is AccessControl, ReentrancyGuard {
address stablecoinToken,
uint256 amountIn
) external view returns (uint256) {
if (dodoLiquidityProvider != address(0)) {
if (!ILiquidityProvider(dodoLiquidityProvider).supportsTokenPair(weth, stablecoinToken)) {
return 0;
}
(uint256 amountOut,) = ILiquidityProvider(dodoLiquidityProvider).getQuote(weth, stablecoinToken, amountIn);
return amountOut;
}
if (dodoPoolAddresses[weth][stablecoinToken] == address(0)) {
return 0;
}
return IDodoexRouter(dodoexRouter).getDodoSwapQuote(weth, stablecoinToken, amountIn);
}
function _hasDodoRoute(
address tokenIn,
address tokenOut,
address configuredPool
) internal view returns (bool) {
if (dodoLiquidityProvider != address(0)) {
return ILiquidityProvider(dodoLiquidityProvider).supportsTokenPair(tokenIn, tokenOut);
}
return configuredPool != address(0);
}
/**
* @notice Get Balancer quote (view)
* When poolId configured, would query Balancer. Otherwise estimate for stablecoins.
@@ -686,4 +744,3 @@ contract EnhancedSwapRouter is AccessControl, ReentrancyGuard {
// Allow contract to receive ETH
receive() external payable {}
}

View File

@@ -110,6 +110,12 @@ contract DODOPMMIntegration is AccessControl, ReentrancyGuard {
);
event PoolRemoved(address indexed pool);
event ReserveSystemSet(address indexed reserveSystem);
event PoolImported(
address indexed pool,
address indexed baseToken,
address indexed quoteToken,
address importer
);
constructor(
address admin,
@@ -164,22 +170,7 @@ contract DODOPMMIntegration is AccessControl, ReentrancyGuard {
isOpenTWAP // Enable TWAP
);
// Register pool
pools[compliantUSDT][officialUSDT] = pool;
pools[officialUSDT][compliantUSDT] = pool;
isRegisteredPool[pool] = true;
allPools.push(pool);
poolConfigs[pool] = PoolConfig({
pool: pool,
baseToken: compliantUSDT,
quoteToken: officialUSDT,
lpFeeRate: lpFeeRate,
i: initialPrice,
k: k,
isOpenTWAP: isOpenTWAP,
createdAt: block.timestamp
});
_recordPool(pool, compliantUSDT, officialUSDT, lpFeeRate, initialPrice, k, isOpenTWAP);
emit PoolCreated(pool, compliantUSDT, officialUSDT, msg.sender);
}
@@ -208,21 +199,7 @@ contract DODOPMMIntegration is AccessControl, ReentrancyGuard {
isOpenTWAP
);
pools[compliantUSDC][officialUSDC] = pool;
pools[officialUSDC][compliantUSDC] = pool;
isRegisteredPool[pool] = true;
allPools.push(pool);
poolConfigs[pool] = PoolConfig({
pool: pool,
baseToken: compliantUSDC,
quoteToken: officialUSDC,
lpFeeRate: lpFeeRate,
i: initialPrice,
k: k,
isOpenTWAP: isOpenTWAP,
createdAt: block.timestamp
});
_recordPool(pool, compliantUSDC, officialUSDC, lpFeeRate, initialPrice, k, isOpenTWAP);
emit PoolCreated(pool, compliantUSDC, officialUSDC, msg.sender);
}
@@ -251,21 +228,7 @@ contract DODOPMMIntegration is AccessControl, ReentrancyGuard {
isOpenTWAP
);
pools[compliantUSDT][compliantUSDC] = pool;
pools[compliantUSDC][compliantUSDT] = pool;
isRegisteredPool[pool] = true;
allPools.push(pool);
poolConfigs[pool] = PoolConfig({
pool: pool,
baseToken: compliantUSDT,
quoteToken: compliantUSDC,
lpFeeRate: lpFeeRate,
i: initialPrice,
k: k,
isOpenTWAP: isOpenTWAP,
createdAt: block.timestamp
});
_recordPool(pool, compliantUSDT, compliantUSDC, lpFeeRate, initialPrice, k, isOpenTWAP);
emit PoolCreated(pool, compliantUSDT, compliantUSDC, msg.sender);
}
@@ -301,25 +264,46 @@ contract DODOPMMIntegration is AccessControl, ReentrancyGuard {
isOpenTWAP
);
pools[baseToken][quoteToken] = pool;
pools[quoteToken][baseToken] = pool;
isRegisteredPool[pool] = true;
allPools.push(pool);
poolConfigs[pool] = PoolConfig({
pool: pool,
baseToken: baseToken,
quoteToken: quoteToken,
lpFeeRate: lpFeeRate,
i: initialPrice,
k: k,
isOpenTWAP: isOpenTWAP,
createdAt: block.timestamp
});
_recordPool(pool, baseToken, quoteToken, lpFeeRate, initialPrice, k, isOpenTWAP);
emit PoolCreated(pool, baseToken, quoteToken, msg.sender);
}
/**
* @notice Import an already-deployed DODO PMM pool into integration state.
* @dev Use this when the pool exists at the DODO/provider layer but was not
* recorded in the integration mappings or allPools inventory.
*/
function importExistingPool(
address pool,
address baseToken,
address quoteToken,
uint256 lpFeeRate,
uint256 initialPrice,
uint256 k,
bool isOpenTWAP
) external onlyRole(POOL_MANAGER_ROLE) {
require(pool != address(0), "DODOPMMIntegration: zero pool");
require(baseToken != address(0), "DODOPMMIntegration: zero base");
require(quoteToken != address(0), "DODOPMMIntegration: zero quote");
require(baseToken != quoteToken, "DODOPMMIntegration: same token");
require(pools[baseToken][quoteToken] == address(0), "DODOPMMIntegration: pair already recorded");
require(!isRegisteredPool[pool], "DODOPMMIntegration: pool already registered");
address actualBase = IDODOPMMPool(pool)._BASE_TOKEN_();
address actualQuote = IDODOPMMPool(pool)._QUOTE_TOKEN_();
bool matchesForward = actualBase == baseToken && actualQuote == quoteToken;
bool matchesReverse = actualBase == quoteToken && actualQuote == baseToken;
require(matchesForward || matchesReverse, "DODOPMMIntegration: pool token mismatch");
if (matchesReverse) {
(baseToken, quoteToken) = (quoteToken, baseToken);
}
_recordPool(pool, baseToken, quoteToken, lpFeeRate, initialPrice, k, isOpenTWAP);
emit PoolImported(pool, baseToken, quoteToken, msg.sender);
}
/**
* @notice Add liquidity to a DODO PMM pool
* @param pool Pool address
@@ -595,5 +579,30 @@ contract DODOPMMIntegration is AccessControl, ReentrancyGuard {
emit PoolRemoved(pool);
}
}
function _recordPool(
address pool,
address baseToken,
address quoteToken,
uint256 lpFeeRate,
uint256 initialPrice,
uint256 k,
bool isOpenTWAP
) internal {
pools[baseToken][quoteToken] = pool;
pools[quoteToken][baseToken] = pool;
isRegisteredPool[pool] = true;
allPools.push(pool);
poolConfigs[pool] = PoolConfig({
pool: pool,
baseToken: baseToken,
quoteToken: quoteToken,
lpFeeRate: lpFeeRate,
i: initialPrice,
k: k,
isOpenTWAP: isOpenTWAP,
createdAt: block.timestamp
});
}
}

View File

@@ -20,8 +20,8 @@ contract PriceFeedKeeper is AccessControl, ReentrancyGuard {
address[] public trackedAssets;
mapping(address => bool) public isTracked;
// Update configuration
uint256 public updateInterval = 30; // seconds
// Update configuration (default 6s aligns with PMM mesh automation; admin may set via setUpdateInterval)
uint256 public updateInterval = 6; // seconds
mapping(address => uint256) public lastUpdateTime;
// Keeper configuration

View File

@@ -11,6 +11,12 @@ import "../compliance/LegallyCompliantBase.sol";
* @notice Generic ISO-4217 compliant fiat/commodity token (ERC-20, DEX-ready)
* @dev Use for cEURC, cGBPC, cAUDC, cJPYC, cCHFC, cCADC, cXAUC, cXAUT, etc.
* Full ERC-20 for DEX liquidity pools; inherits LegallyCompliantBase.
*
* XAU (gold) invariant — enforced by policy and integrators, not by ERC-20 math:
* When `currencyCode()` is `"XAU"` (e.g. cXAUC, cXAUT), **one full token** means
* **exactly one troy ounce** of fine gold: balances and `mint`/`transfer` amounts use
* `10 ** decimals()` base units per troy ounce (with 6 decimals, `1_000_000` base = 1 oz).
* Fiat codes (USD, EUR, …) use one full token as one unit of that currency at `decimals`.
*/
contract CompliantFiatToken is ERC20, Pausable, Ownable, LegallyCompliantBase {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");

View File

@@ -0,0 +1,40 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title OfficialStableMirrorToken
* @notice Lightweight ERC-20 used as the local Chain 138 "official" stable mirror.
* @dev This token exists only to provide a live ERC-20 quote-side asset for local PMM pools.
* It is intentionally separate from the compliant token contracts.
*/
contract OfficialStableMirrorToken is ERC20, Ownable {
uint8 private immutable _decimalsStorage;
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
address initialOwner,
uint256 initialSupply
) ERC20(name_, symbol_) Ownable(initialOwner) {
_decimalsStorage = decimals_;
if (initialSupply > 0) {
_mint(msg.sender, initialSupply);
}
}
function decimals() public view override returns (uint8) {
return _decimalsStorage;
}
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}
function burn(address from, uint256 amount) external onlyOwner {
_burn(from, amount);
}
}