Files
smom-dbis-138/contracts/liquidity/providers/DODOPMMProvider.sol
defiQUG 1511f33857 chore: update DBIS contracts and integrate EIP-712 helper
- Updated DBIS_ConversionRouter and DBIS_SettlementRouter to utilize IDBIS_EIP712Helper for EIP-712 hashing and signature recovery, improving stack depth management.
- Refactored minting logic in DBIS_GRU_MintController to streamline recipient processing.
- Enhanced BUILD_NOTES.md with updated build instructions and test coverage details.
- Added new functions in DBIS_SignerRegistry for duplicate signer checks and active signer validation.
- Introduced a new submodule, DBIS_EIP712Helper, to encapsulate EIP-712 related functionalities.

Made-with: Cursor
2026-03-04 02:00:09 -08:00

204 lines
7.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/ILiquidityProvider.sol";
import "../../dex/DODOPMMIntegration.sol";
/**
* @title DODOPMMProvider
* @notice Wrapper for DODO PMM with extended functionality
* @dev Implements ILiquidityProvider for multi-provider liquidity system
*/
contract DODOPMMProvider is ILiquidityProvider, AccessControl {
using SafeERC20 for IERC20;
bytes32 public constant POOL_MANAGER_ROLE = keccak256("POOL_MANAGER_ROLE");
DODOPMMIntegration public dodoIntegration;
// Pool tracking
mapping(address => mapping(address => address)) public pools; // tokenIn => tokenOut => pool
mapping(address => bool) public isKnownPool;
event PoolCreated(address indexed tokenIn, address indexed tokenOut, address pool);
event PoolOptimized(address indexed pool, uint256 newK, uint256 newI);
constructor(address _dodoIntegration, address admin) {
require(_dodoIntegration != address(0), "Zero address");
dodoIntegration = DODOPMMIntegration(_dodoIntegration);
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(POOL_MANAGER_ROLE, admin);
}
/**
* @notice Get quote from DODO PMM
*/
function getQuote(
address tokenIn,
address tokenOut,
uint256 amountIn
) external view override returns (uint256 amountOut, uint256 slippageBps) {
address pool = pools[tokenIn][tokenOut];
if (pool == address(0)) {
return (0, 10000); // No pool, 100% slippage
}
try dodoIntegration.getPoolPriceOrOracle(pool) returns (uint256 price) {
// Simple calculation (in production, would use actual DODO math)
amountOut = (amountIn * price) / 1e18;
slippageBps = 30; // 0.3% typical for stablecoin pools
return (amountOut, slippageBps);
} catch {
return (0, 10000);
}
}
/**
* @notice Execute swap via DODO PMM
*/
function executeSwap(
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 minAmountOut
) external override returns (uint256 amountOut) {
// Get pool for token pair
address pool = pools[tokenIn][tokenOut];
require(pool != address(0), "Pool not found");
// Transfer tokens from caller
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
// Route to appropriate swap method: use dedicated methods for the 6 legacy pairs,
// otherwise use generic swapExactIn for full-mesh routing (any registered pool).
if (tokenIn == dodoIntegration.compliantUSDT() && tokenOut == dodoIntegration.officialUSDT()) {
IERC20(tokenIn).approve(address(dodoIntegration), amountIn);
amountOut = dodoIntegration.swapCUSDTForUSDT(pool, amountIn, minAmountOut);
} else if (tokenIn == dodoIntegration.officialUSDT() && tokenOut == dodoIntegration.compliantUSDT()) {
IERC20(tokenIn).approve(address(dodoIntegration), amountIn);
amountOut = dodoIntegration.swapUSDTForCUSDT(pool, amountIn, minAmountOut);
} else if (tokenIn == dodoIntegration.compliantUSDC() && tokenOut == dodoIntegration.officialUSDC()) {
IERC20(tokenIn).approve(address(dodoIntegration), amountIn);
amountOut = dodoIntegration.swapCUSDCForUSDC(pool, amountIn, minAmountOut);
} else if (tokenIn == dodoIntegration.officialUSDC() && tokenOut == dodoIntegration.compliantUSDC()) {
IERC20(tokenIn).approve(address(dodoIntegration), amountIn);
amountOut = dodoIntegration.swapUSDCForCUSDC(pool, amountIn, minAmountOut);
} else if (tokenIn == dodoIntegration.compliantUSDT() && tokenOut == dodoIntegration.compliantUSDC()) {
IERC20(tokenIn).approve(address(dodoIntegration), amountIn);
amountOut = dodoIntegration.swapCUSDTForUSDC(pool, amountIn, minAmountOut);
} else if (tokenIn == dodoIntegration.compliantUSDC() && tokenOut == dodoIntegration.compliantUSDT()) {
IERC20(tokenIn).approve(address(dodoIntegration), amountIn);
amountOut = dodoIntegration.swapUSDCForCUSDT(pool, amountIn, minAmountOut);
} else {
// Full mesh: any registered pool (c* vs c*, c* vs official, etc.)
IERC20(tokenIn).approve(address(dodoIntegration), amountIn);
amountOut = dodoIntegration.swapExactIn(pool, tokenIn, amountIn, minAmountOut);
}
// Transfer output tokens to caller
IERC20(tokenOut).safeTransfer(msg.sender, amountOut);
return amountOut;
}
/**
* @notice Check if provider supports token pair
*/
function supportsTokenPair(
address tokenIn,
address tokenOut
) external view override returns (bool) {
return pools[tokenIn][tokenOut] != address(0);
}
/**
* @notice Get provider name
*/
function providerName() external pure override returns (string memory) {
return "DODO PMM";
}
/**
* @notice Estimate gas for swap
*/
function estimateGas(
address,
address,
uint256
) external pure override returns (uint256) {
return 150000; // Typical gas for DODO swap
}
/**
* @notice Ensure pool exists for token pair
*/
function ensurePoolExists(address tokenIn, address tokenOut) external onlyRole(POOL_MANAGER_ROLE) {
if (pools[tokenIn][tokenOut] == address(0)) {
_createOptimalPool(tokenIn, tokenOut);
}
}
/// @dev Default params for stablecoin pairs: 0.03% fee, 1:1 price, k=0.5e18
uint256 private constant DEFAULT_LP_FEE = 3;
uint256 private constant DEFAULT_I = 1e18;
uint256 private constant DEFAULT_K = 0.5e18;
/**
* @notice Create optimal DODO pool via DODOPMMIntegration
* @dev Requires DODOPMMIntegration to grant POOL_MANAGER_ROLE to this contract
*/
function _createOptimalPool(address tokenIn, address tokenOut) internal {
address pool = dodoIntegration.createPool(
tokenIn,
tokenOut,
DEFAULT_LP_FEE,
DEFAULT_I,
DEFAULT_K,
false // isOpenTWAP - disable for stablecoins
);
pools[tokenIn][tokenOut] = pool;
pools[tokenOut][tokenIn] = pool;
isKnownPool[pool] = true;
emit PoolCreated(tokenIn, tokenOut, pool);
}
/**
* @notice Register existing pool
*/
function registerPool(
address tokenIn,
address tokenOut,
address pool
) external onlyRole(POOL_MANAGER_ROLE) {
require(pool != address(0), "Zero address");
pools[tokenIn][tokenOut] = pool;
isKnownPool[pool] = true;
emit PoolCreated(tokenIn, tokenOut, pool);
}
/**
* @notice Optimize pool parameters (K, I)
* @dev DODO PMM parameters are typically oracle-driven; DVM pools may expose
* setK/setI. Emits for off-chain monitoring. If the pool supports
* parameter updates, extend this to call the pool's update functions.
*/
function optimizePoolParameters(
address pool,
uint256 newK,
uint256 newI
) external onlyRole(POOL_MANAGER_ROLE) {
require(isKnownPool[pool], "Unknown pool");
// DODO DVM/PMM: parameters set at creation; oracle-driven rebalancing.
// Emit for observability; integrate pool.setK/setI when supported.
emit PoolOptimized(pool, newK, newI);
}
}