From 7ebf770bf06f00c7cf18c9e51c3bebc4f22fc767 Mon Sep 17 00:00:00 2001 From: 0xtj24 Date: Thu, 25 Sep 2025 16:15:28 +0200 Subject: [PATCH 1/2] add Dola-WstUSR tests --- test/feedForkTests/DolawstUSRFeedFork.t.sol | 23 ++++ .../DolaWstUSRConvexMarketForkTest.t.sol | 100 ++++++++++++++++++ .../DolaWstUSRYearnV2MarketForkTest.t.sol | 66 ++++++++++++ test/util/aleTests/ALEDolaWstUSR.t.sol | 47 ++++++++ test/util/aleTests/ALEDolaWstUSRYearnV2.t.sol | 48 +++++++++ 5 files changed, 284 insertions(+) create mode 100644 test/feedForkTests/DolawstUSRFeedFork.t.sol create mode 100644 test/marketForkTests/DolaWstUSRConvexMarketForkTest.t.sol create mode 100644 test/marketForkTests/DolaWstUSRYearnV2MarketForkTest.t.sol create mode 100644 test/util/aleTests/ALEDolaWstUSR.t.sol create mode 100644 test/util/aleTests/ALEDolaWstUSRYearnV2.t.sol diff --git a/test/feedForkTests/DolawstUSRFeedFork.t.sol b/test/feedForkTests/DolawstUSRFeedFork.t.sol new file mode 100644 index 0000000..c8da1d4 --- /dev/null +++ b/test/feedForkTests/DolawstUSRFeedFork.t.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import "forge-std/Test.sol"; +import "src/feeds/ChainlinkBasePriceFeed.sol"; +import {ChainlinkCurveFeed} from "src/feeds/ChainlinkCurveFeed.sol"; +import {ChainlinkCurve2CoinsFeed} from "src/feeds/ChainlinkCurve2CoinsFeed.sol"; +import "src/feeds/CurveLPPessimisticFeed.sol"; +import {DolaCurveLPPessimsticFeedBaseTest} from "test/feedForkTests/DolaCurveLPPessimsticFeedBaseTest.t.sol"; +import {ConfigAddr} from "test/ConfigAddr.sol"; +import {ERC4626Feed} from "src/feeds/ERC4626Feed.sol"; + +contract DolaWstUSRUSDFeedFork is DolaCurveLPPessimsticFeedBaseTest, ConfigAddr { + ICurvePool public constant dolawstUSR = + ICurvePool(0x64273624eb57c5cA961d366CBF3968e760Bf0452); + address usrWrapper = address(0x182Af82E3619D2182b3669BbFA8C72bC57614aDf); + function setUp() public { + string memory url = vm.rpcUrl("mainnet"); + vm.createSelectFork(url); + + init(address(0), address(usrWrapper), address(dolawstUSR)); + } +} diff --git a/test/marketForkTests/DolaWstUSRConvexMarketForkTest.t.sol b/test/marketForkTests/DolaWstUSRConvexMarketForkTest.t.sol new file mode 100644 index 0000000..21c4644 --- /dev/null +++ b/test/marketForkTests/DolaWstUSRConvexMarketForkTest.t.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {MarketBaseForkTest, IOracle, IDolaBorrowingRights, IERC20} from "./MarketBaseForkTest.sol"; +import {Market} from "src/Market.sol"; + +import {ConvexEscrowV2} from "src/escrows/ConvexEscrowV2.sol"; +import {CurveLPPessimisticFeed} from "src/feeds/CurveLPPessimisticFeed.sol"; +import {ChainlinkCurve2CoinsFeed, ICurvePool} from "src/feeds/ChainlinkCurve2CoinsFeed.sol"; +import {ChainlinkCurveFeed} from "src/feeds/ChainlinkCurveFeed.sol"; +import "src/feeds/ChainlinkBasePriceFeed.sol"; +import {console} from "forge-std/console.sol"; +import {YearnVaultV2Helper, IYearnVaultV2} from "src/util/YearnVaultV2Helper.sol"; +import {DolaFixedPriceFeed} from "src/feeds/DolaFixedPriceFeed.sol"; +import {ChainlinkBasePriceFeed} from "src/feeds/ChainlinkBasePriceFeed.sol"; +import {MockFeedDescription} from "test/mocks/MockFeedDescription.sol"; + +contract DolaWstUSRConvexMarketForkTest is MarketBaseForkTest { + ConvexEscrowV2 escrow; + + CurveLPPessimisticFeed feedDolaUSR; + DolaFixedPriceFeed dolaFeed; + + ICurvePool public constant dolaWstUSR = + ICurvePool(0x64273624eb57c5cA961d366CBF3968e760Bf0452); + + address usrWrapper = address(0x182Af82E3619D2182b3669BbFA8C72bC57614aDf); + + address rewardPool = address(0x7F548ca54A86a326CE42772879338d429F14f048); + + address booster = address(0xF403C135812408BFbE8713b5A23a04b3D48AAE31); + + uint256 pid = 496; + + IERC20 public cvx = IERC20(0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B); + IERC20 public crv = IERC20(0xD533a949740bb3306d119CC777fa900bA034cd52); + + ConvexEscrowV2 userEscrow; + + function setUp() public virtual { + //This will fail if there's no mainnet variable in foundry.toml + string memory url = vm.rpcUrl("mainnet"); + vm.createSelectFork(url); + escrow = new ConvexEscrowV2( + rewardPool, + booster, + address(cvx), + address(crv), + pid + ); + feedDolaUSR = _deployDolaUSRFeed(); + market = new Market( + gov, + fedAddr, + pauseGuardian, + address(escrow), + IDolaBorrowingRights(address(dbrAddr)), + IERC20(address(dolaWstUSR)), + IOracle(address(oracleAddr)), + 5000, + 5000, + 100, + true + ); + _advancedInit(address(market), address(feedDolaUSR), true); + + userEscrow = ConvexEscrowV2( + address(Market(address(market)).predictEscrow(user)) + ); + } + + function test_escrow_immutables() public { + testDeposit(); + assertEq( + address(userEscrow.rewardPool()), + address(rewardPool), + "Reward pool not set" + ); + assertEq( + address(userEscrow.booster()), + address(booster), + "Booster not set" + ); + + assertEq(address(userEscrow.cvx()), address(cvx), "CVX not set"); + assertEq(address(userEscrow.crv()), address(crv), "CRV not set"); + } + + function _deployDolaUSRFeed() + internal + returns (CurveLPPessimisticFeed feed) + { + feed = new CurveLPPessimisticFeed( + address(dolaWstUSR), + address(usrWrapper), + address(dolaFixedFeedAddr), + false + ); + } +} diff --git a/test/marketForkTests/DolaWstUSRYearnV2MarketForkTest.t.sol b/test/marketForkTests/DolaWstUSRYearnV2MarketForkTest.t.sol new file mode 100644 index 0000000..7704d9c --- /dev/null +++ b/test/marketForkTests/DolaWstUSRYearnV2MarketForkTest.t.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {MarketBaseForkTest, IOracle, IDolaBorrowingRights, IERC20} from "./MarketBaseForkTest.sol"; +import {Market} from "src/Market.sol"; +import {SimpleERC20Escrow} from "src/escrows/SimpleERC20Escrow.sol"; +import {CurveLPYearnV2Feed} from "src/feeds/CurveLPYearnV2Feed.sol"; +import {ChainlinkCurve2CoinsFeed} from "src/feeds/ChainlinkCurve2CoinsFeed.sol"; +import {ChainlinkCurveFeed, ICurvePool} from "src/feeds/ChainlinkCurveFeed.sol"; +import "src/feeds/ChainlinkBasePriceFeed.sol"; +import "src/feeds/CurveLPYearnV2Feed.sol"; +import {console} from "forge-std/console.sol"; +import {YearnVaultV2Helper, IYearnVaultV2} from "src/util/YearnVaultV2Helper.sol"; +import {CurveLPPessimisticFeed} from "src/feeds/CurveLPPessimisticFeed.sol"; +import {MockFeedDescription} from "test/mocks/MockFeedDescription.sol"; +import {ChainlinkBasePriceFeed} from "src/feeds/ChainlinkBasePriceFeed.sol"; + +contract DolaWstUSRYearnV2MarketForkTest is MarketBaseForkTest { + CurveLPYearnV2Feed yearnFeed; + CurveLPPessimisticFeed lpFeed; + + address usrWrapper = address(0x182Af82E3619D2182b3669BbFA8C72bC57614aDf); + + ICurvePool public constant dolaWstUSR = + ICurvePool(0x64273624eb57c5cA961d366CBF3968e760Bf0452); + + address public constant yearn = + address(0x8A5f20dA6B393fE25aCF1522C828166D22eF8321); + + function setUp() public virtual { + //This will fail if there's no mainnet variable in foundry.toml + string memory url = vm.rpcUrl("mainnet"); + vm.createSelectFork(url); + + Market market = new Market( + gov, + lender, + pauseGuardian, + address(simpleERC20EscrowAddr), + IDolaBorrowingRights(address(dbr)), + IERC20(address(yearn)), + IOracle(address(oracle)), + 5000, + 5000, + 1000, + false + ); + yearnFeed = _deployDolaUSRYearnV2Feed(); + _advancedInit(address(market), address(yearnFeed), true); + } + + function _deployDolaUSRYearnV2Feed() + internal + returns (CurveLPYearnV2Feed feed) + { + + lpFeed = new CurveLPPessimisticFeed( + address(dolaWstUSR), + address(usrWrapper), + address(dolaFixedFeedAddr), + false + ); + + feed = new CurveLPYearnV2Feed(address(yearn), address(lpFeed)); + } +} diff --git a/test/util/aleTests/ALEDolaWstUSR.t.sol b/test/util/aleTests/ALEDolaWstUSR.t.sol new file mode 100644 index 0000000..5adf69b --- /dev/null +++ b/test/util/aleTests/ALEDolaWstUSR.t.sol @@ -0,0 +1,47 @@ +pragma solidity ^0.8.13; + +import {ICurvePool} from "src/interfaces/ICurvePool.sol"; +import {CurveDolaLPHelperDynamic} from "src/util/CurveDolaLPHelperDynamic.sol"; +import "test/marketForkTests/DolaWstUSRConvexMarketForkTest.t.sol"; +import {console} from "forge-std/console.sol"; +import {IMultiMarketTransformHelper} from "src/interfaces/IMultiMarketTransformHelper.sol"; +import {ALEV2} from "src/util/ALEV2.sol"; +import {ALEBaseDolaLPDynTest, IFlashMinter} from "test/util/aleTests/ALEBaseDolaLPDyn.sol"; + +contract ALEDolaWstUSRTest is + ALEBaseDolaLPDynTest, + DolaWstUSRConvexMarketForkTest +{ + address wstUSR = address(0x1202F5C7b4B9E47a1A484E8B270be34dbbC75055); + + function setUp() public override { + super.setUp(); + curvePool = dolaWstUSR; + + helper = CurveDolaLPHelperDynamic(curveDolaLPHelperDynamicAddr); + + vm.startPrank(gov); + DOLA.mint(address(this), 100000 ether); + helper.setMarket(address(market), address(curvePool), 0, 2, address(0)); + ale = ALEV2(payable(aleV2Addr)); + ale.setMarket(address(market), address(DOLA), address(helper), false); + + borrowController.allow(address(ale)); + vm.stopPrank(); + userPkEscrow = address(market.predictEscrow(userPk)); + _seedPool(); + } + + function _seedPool() internal{ + // Seed the pool with 902153 wstETH and 1000000 DOLA + deal(wstUSR, address(this), 902153 ether, true); + vm.prank(gov); + DOLA.mint(address(this), 1000000 ether); + IERC20(wstUSR).approve(address(curvePool), type(uint256).max); + DOLA.approve(address(curvePool), type(uint256).max); + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000000 ether; + amounts[1] = 902153 ether; + curvePool.add_liquidity(amounts, 0, address(this)); + } +} diff --git a/test/util/aleTests/ALEDolaWstUSRYearnV2.t.sol b/test/util/aleTests/ALEDolaWstUSRYearnV2.t.sol new file mode 100644 index 0000000..9d489b1 --- /dev/null +++ b/test/util/aleTests/ALEDolaWstUSRYearnV2.t.sol @@ -0,0 +1,48 @@ +pragma solidity ^0.8.13; + +import {ICurvePool} from "src/interfaces/ICurvePool.sol"; +import {CurveDolaLPHelperDynamic} from "src/util/CurveDolaLPHelperDynamic.sol"; +import "test/marketForkTests/DolaWstUSRYearnV2MarketForkTest.t.sol"; +import {console} from "forge-std/console.sol"; +import {IMultiMarketTransformHelper} from "src/interfaces/IMultiMarketTransformHelper.sol"; +import {ALEV2} from "src/util/ALEV2.sol"; +import {YearnVaultV2Helper, IYearnVaultV2} from "src/util/YearnVaultV2Helper.sol"; +import {ALEBaseDolaLPDynYearnV2Test, IFlashMinter} from "test/util/aleTests/ALEBaseDolaLPDynYearnV2.sol"; + +contract ALEDolaWstUSRYearnV2Test is + ALEBaseDolaLPDynYearnV2Test, + DolaWstUSRYearnV2MarketForkTest +{ + address wstUSR = address(0x1202F5C7b4B9E47a1A484E8B270be34dbbC75055); + + function setUp() public override { + super.setUp(); + + helper = CurveDolaLPHelperDynamic(curveDolaLPHelperDynamicAddr); + curvePool = dolaWstUSR; + vault = IYearnVaultV2(yearn); + vm.startPrank(gov); + DOLA.mint(address(this), 100000 ether); + helper.setMarket(address(market), address(curvePool), 0, 2, yearn); + ale = ALEV2(payable(aleV2Addr)); + ale.setMarket(address(market), address(DOLA), address(helper), false); + + borrowController.allow(address(ale)); + vm.stopPrank(); + userPkEscrow = address(market.predictEscrow(userPk)); + _seedPool(); + } + + function _seedPool() internal{ + // Seed the pool with 902153 wstETH and 1000000 DOLA + deal(wstUSR, address(this), 902153 ether, true); + vm.prank(gov); + DOLA.mint(address(this), 1000000 ether); + IERC20(wstUSR).approve(address(curvePool), type(uint256).max); + DOLA.approve(address(curvePool), type(uint256).max); + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000000 ether; + amounts[1] = 902153 ether; + curvePool.add_liquidity(amounts, 0, address(this)); + } +} From c81396f90c3f57901177dafe68a4de737b030fae Mon Sep 17 00:00:00 2001 From: 0xtj24 Date: Thu, 25 Sep 2025 16:26:10 +0200 Subject: [PATCH 2/2] add feed test for Yearn market, rm old empty test files --- .../CurveLPPessimsticFeedBaseTest.t.sol | 0 ...CurveLPPessimsticYearnV2FeedBaseTest.t.sol | 0 .../CurveLPSingleFeedBaseTest.t.sol | 0 .../DolawstUSRYearnV2FeedFork.t.sol | 33 +++++++++++++++++++ 4 files changed, 33 insertions(+) delete mode 100644 test/feedForkTests/CurveLPPessimsticFeedBaseTest.t.sol delete mode 100644 test/feedForkTests/CurveLPPessimsticYearnV2FeedBaseTest.t.sol delete mode 100644 test/feedForkTests/CurveLPSingleFeedBaseTest.t.sol create mode 100644 test/feedForkTests/DolawstUSRYearnV2FeedFork.t.sol diff --git a/test/feedForkTests/CurveLPPessimsticFeedBaseTest.t.sol b/test/feedForkTests/CurveLPPessimsticFeedBaseTest.t.sol deleted file mode 100644 index e69de29..0000000 diff --git a/test/feedForkTests/CurveLPPessimsticYearnV2FeedBaseTest.t.sol b/test/feedForkTests/CurveLPPessimsticYearnV2FeedBaseTest.t.sol deleted file mode 100644 index e69de29..0000000 diff --git a/test/feedForkTests/CurveLPSingleFeedBaseTest.t.sol b/test/feedForkTests/CurveLPSingleFeedBaseTest.t.sol deleted file mode 100644 index e69de29..0000000 diff --git a/test/feedForkTests/DolawstUSRYearnV2FeedFork.t.sol b/test/feedForkTests/DolawstUSRYearnV2FeedFork.t.sol new file mode 100644 index 0000000..0e8906e --- /dev/null +++ b/test/feedForkTests/DolawstUSRYearnV2FeedFork.t.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import "forge-std/Test.sol"; +import "src/feeds/ChainlinkBasePriceFeed.sol"; +import {ChainlinkCurveFeed} from "src/feeds/ChainlinkCurveFeed.sol"; +import "src/feeds/CurveLPPessimisticFeed.sol"; +import {CurveLPYearnV2FeedBaseTest} from "test/feedForkTests/CurveLPYearnV2FeedBaseTest.t.sol"; + +contract DolawstUSRYearnV2FeedFork is CurveLPYearnV2FeedBaseTest { + ICurvePool public constant dolawstUSR = + ICurvePool(0x64273624eb57c5cA961d366CBF3968e760Bf0452); + + address usrWrapper = address(0x182Af82E3619D2182b3669BbFA8C72bC57614aDf); + + address public constant yearnVault = + address(0x8A5f20dA6B393fE25aCF1522C828166D22eF8321); + + CurveLPPessimisticFeed dolaWstUSRFeed; + + function setUp() public { + string memory url = vm.rpcUrl("mainnet"); + vm.createSelectFork(url); + + dolaWstUSRFeed = new CurveLPPessimisticFeed( + address(dolawstUSR), + usrWrapper, + dolaFixedFeedAddr, + false + ); + init(address(dolaWstUSRFeed), address(dolawstUSR), yearnVault); + } +}