// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {Script, console} from "forge-std/Script.sol"; import {DODOPMMIntegration} from "../../contracts/dex/DODOPMMIntegration.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title AddLiquidityPMMPoolsChain138 * @notice Add liquidity to the three DODO PMM pools on Chain 138 (cUSDT/cUSDC, cUSDT/USDT, cUSDC/USDC). * @dev Env: PRIVATE_KEY, RPC_URL_138, DODO_PMM_INTEGRATION_ADDRESS (or DODO_PMM_INTEGRATION), * POOL_CUSDTCUSDC, POOL_CUSDTUSDT, POOL_CUSDCUSDC, * ADD_LIQUIDITY_BASE_AMOUNT, ADD_LIQUIDITY_QUOTE_AMOUNT (e.g. 1000000e6 for 1M units, 6 decimals). * Optional: ADD_LIQUIDITY_CUSDTCUSDC_BASE, ADD_LIQUIDITY_CUSDTCUSDC_QUOTE, etc. for per-pool amounts. * Optional: NEXT_NONCE — set to pending nonce (e.g. after mints) to avoid -32001 "Nonce too low" on broadcast. */ contract AddLiquidityPMMPoolsChain138 is Script { function run() external { uint256 pk = vm.envUint("PRIVATE_KEY"); address deployer = vm.addr(pk); address integrationAddr = vm.envAddress("DODO_PMM_INTEGRATION"); if (integrationAddr == address(0)) integrationAddr = vm.envAddress("DODO_PMM_INTEGRATION_ADDRESS"); require(integrationAddr != address(0), "DODO_PMM_INTEGRATION not set"); // Use explicit nonce when set (e.g. after mints in same session) to avoid -32001 "Nonce too low" uint64 nextNonce = uint64(vm.envOr("NEXT_NONCE", uint256(0))); if (nextNonce > 0) { vm.setNonce(deployer, nextNonce); } address poolCusdtCusdc = vm.envOr("POOL_CUSDTCUSDC", address(0)); address poolCusdtUsdt = vm.envOr("POOL_CUSDTUSDT", address(0)); address poolCusdcUsdc = vm.envOr("POOL_CUSDCUSDC", address(0)); uint256 defaultBase = vm.envOr("ADD_LIQUIDITY_BASE_AMOUNT", uint256(0)); uint256 defaultQuote = vm.envOr("ADD_LIQUIDITY_QUOTE_AMOUNT", uint256(0)); DODOPMMIntegration integration = DODOPMMIntegration(integrationAddr); address cusdt = integration.compliantUSDT(); address cusdc = integration.compliantUSDC(); address usdt = integration.officialUSDT(); address usdc = integration.officialUSDC(); // On Chain 138, DODOPMMIntegration may have been deployed with mainnet official USDT/USDC // (0xdAC17F958D2ee523a2206206994597C13D831ec7, 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48). // Those addresses have no code on 138, so skip cUSDT/USDT and cUSDC/USDC to avoid "call to non-contract". bool skipOfficialPools = block.chainid == 138 && ( !_isContract(usdt) || !_isContract(usdc) ); vm.startBroadcast(pk); if (poolCusdtCusdc != address(0) && (defaultBase > 0 || defaultQuote > 0)) { uint256 b = vm.envOr("ADD_LIQUIDITY_CUSDTCUSDC_BASE", defaultBase); uint256 q = vm.envOr("ADD_LIQUIDITY_CUSDTCUSDC_QUOTE", defaultQuote); if (b > 0 && q > 0) { _approveAndAdd(integration, cusdt, cusdc, poolCusdtCusdc, b, q); console.log("Added liquidity to cUSDT/cUSDC pool:", poolCusdtCusdc); } } if (!skipOfficialPools && poolCusdtUsdt != address(0) && (defaultBase > 0 || defaultQuote > 0)) { uint256 b = vm.envOr("ADD_LIQUIDITY_CUSDTUSDT_BASE", defaultBase); uint256 q = vm.envOr("ADD_LIQUIDITY_CUSDTUSDT_QUOTE", defaultQuote); if (b > 0 && q > 0) { _approveAndAdd(integration, cusdt, usdt, poolCusdtUsdt, b, q); console.log("Added liquidity to cUSDT/USDT pool:", poolCusdtUsdt); } } if (!skipOfficialPools && poolCusdcUsdc != address(0) && (defaultBase > 0 || defaultQuote > 0)) { uint256 b = vm.envOr("ADD_LIQUIDITY_CUSDCUSDC_BASE", defaultBase); uint256 q = vm.envOr("ADD_LIQUIDITY_CUSDCUSDC_QUOTE", defaultQuote); if (b > 0 && q > 0) { _approveAndAdd(integration, cusdc, usdc, poolCusdcUsdc, b, q); console.log("Added liquidity to cUSDC/USDC pool:", poolCusdcUsdc); } } vm.stopBroadcast(); } function _isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } function _approveAndAdd( DODOPMMIntegration integration, address baseToken, address quoteToken, address pool, uint256 baseAmount, uint256 quoteAmount ) internal { IERC20(baseToken).approve(address(integration), type(uint256).max); IERC20(quoteToken).approve(address(integration), type(uint256).max); integration.addLiquidity(pool, baseAmount, quoteAmount); } }