// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Test, console} from "forge-std/Test.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; interface IDODOPMMIntegrationSeedFork { function isRegisteredPool(address pool) external view returns (bool); function addLiquidity(address pool, uint256 baseAmount, uint256 quoteAmount) external returns (uint256 baseShare, uint256 quoteShare, uint256 lpShare); } interface IDODOPMMPoolSeedFork { function _BASE_TOKEN_() external view returns (address); function _QUOTE_TOKEN_() external view returns (address); function getVaultReserve() external view returns (uint256 baseReserve, uint256 quoteReserve); function getMidPrice() external view returns (uint256); } /// @notice Mainnet fork validation for permanent cWUSDC/USDC and cWUSDT/USDT DODO seed paths. contract SeedMainnetCwStablePoolPermanentForkTest is Test { using SafeERC20 for IERC20; address internal constant INTEGRATION = 0xa9F284eD010f4F7d7F8F201742b49b9f58e29b84; address internal constant POOL_USDC = 0x69776fc607e9edA8042e320e7e43f54d06c68f0E; address internal constant POOL_USDT = 0x79156F6B7bf71a1B72D78189B540A89A6C13F6FC; address internal constant CWUSDC = 0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a; address internal constant CWUSDT = 0xaF5017d0163ecb99D9B5D94e3b4D7b09Af44D8AE; address internal constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; address internal constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7; uint256 internal constant SEED_RAW = 50_000_000_000; function setUp() public { string memory rpc = vm.envOr("ETHEREUM_MAINNET_RPC", string("https://eth.llamarpc.com")); vm.createSelectFork(rpc); } function test_fork_seed_cWUSDC_USDC_addLiquidity_50k() public { _seedRail(POOL_USDC, CWUSDC, USDC, "USDC"); } function test_fork_seed_cWUSDT_USDT_addLiquidity_50k() public { _seedRail(POOL_USDT, CWUSDT, USDT, "USDT"); } function _ensurePoolRegistered(address pool) internal view { assertTrue(IDODOPMMIntegrationSeedFork(INTEGRATION).isRegisteredPool(pool), "pool not registered on integration"); } function _seedRail(address pool, address baseToken, address quoteToken, string memory label) internal { address user = makeAddr("seedUser"); deal(baseToken, user, SEED_RAW); deal(quoteToken, user, SEED_RAW); IDODOPMMPoolSeedFork poolView = IDODOPMMPoolSeedFork(pool); assertEq(poolView._BASE_TOKEN_(), baseToken, "base token"); assertEq(poolView._QUOTE_TOKEN_(), quoteToken, "quote token"); _ensurePoolRegistered(pool); (uint256 baseBefore, uint256 quoteBefore) = poolView.getVaultReserve(); uint256 midBefore = poolView.getMidPrice(); console.log(string.concat(label, " baseReserveBefore"), baseBefore); console.log(string.concat(label, " quoteReserveBefore"), quoteBefore); console.log(string.concat(label, " midBefore"), midBefore); vm.startPrank(user); IERC20(baseToken).forceApprove(INTEGRATION, SEED_RAW); IERC20(quoteToken).forceApprove(INTEGRATION, SEED_RAW); (uint256 baseShare, uint256 quoteShare, uint256 lpShare) = IDODOPMMIntegrationSeedFork(INTEGRATION).addLiquidity(pool, SEED_RAW, SEED_RAW); vm.stopPrank(); (uint256 baseAfter, uint256 quoteAfter) = poolView.getVaultReserve(); uint256 midAfter = poolView.getMidPrice(); console.log(string.concat(label, " baseShare"), baseShare); console.log(string.concat(label, " quoteShare"), quoteShare); console.log(string.concat(label, " lpShare"), lpShare); console.log(string.concat(label, " baseReserveAfter"), baseAfter); console.log(string.concat(label, " quoteReserveAfter"), quoteAfter); console.log(string.concat(label, " midAfter"), midAfter); assertGt(baseShare, 0, "base share"); assertGt(quoteShare, 0, "quote share"); assertGt(lpShare, 0, "lp share"); assertGt(baseAfter, baseBefore, "base reserve increased"); assertGt(quoteAfter, quoteBefore, "quote reserve increased"); } }