From 2263723bc6d1eb961bc6c5c134e7a83e4f3f53f3 Mon Sep 17 00:00:00 2001 From: Mario <85162486+mario-ipor@users.noreply.github.com> Date: Tue, 13 May 2025 13:32:43 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=F0=9F=91=B7=20Setup=20Wake=20Arena=20(#757?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 👷 Add Wake Arena workflow * Change branch --------- Co-authored-by: rav <85165079+rav-ipor@users.noreply.github.com> --- .github/workflows/wake-arena-audit.yaml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/wake-arena-audit.yaml diff --git a/.github/workflows/wake-arena-audit.yaml b/.github/workflows/wake-arena-audit.yaml new file mode 100644 index 000000000..825268728 --- /dev/null +++ b/.github/workflows/wake-arena-audit.yaml @@ -0,0 +1,22 @@ +name: Wake Arena Audit +run-name: ${{ github.actor }} prepared Wake Arena PR +on: + push: + branches: + - develop +jobs: + perform-audit: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Install dependencies + run: npm install # todo check if the command to install dependencies is correct + - name: Setup Wake + uses: Ackee-Blockchain/wake-setup-action@0.1.0 + - name: Setup Wake Arena + uses: Ackee-Blockchain/wake-arena-setup-action@0.1.1 + - name: Perform audit + env: + WAKE_ARENA_API_KEY: ${{ secrets.WAKE_ARENA_API_KEY }} + run: wake-arena check --name "${{ github.event.head_commit.message }}" --project "FsLgbYu_" From 3134c367c4892d349b913d14719c42371168a926 Mon Sep 17 00:00:00 2001 From: Mario Date: Fri, 16 May 2025 08:38:06 +0200 Subject: [PATCH 2/6] Remove redundant file. Fix initialization --- .../IAmmPoolsServiceWstEthBaseV2.sol | 2 +- .../amm/services/AmmPoolsServiceBaseV1.sol | 2 +- scripts/LocalDeployment.s.sol | 882 ------------------ 3 files changed, 2 insertions(+), 884 deletions(-) delete mode 100644 scripts/LocalDeployment.s.sol diff --git a/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol b/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol index 88fd2b938..6c3bdb73a 100644 --- a/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol +++ b/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; import {IAmmPoolsServiceWstEthBaseV1} from "./IAmmPoolsServiceWstEthBaseV1.sol"; -/// @title Interface of the AmmPoolsServiceWstEth contract V2. +/// @title Interface of the AmmPoolsServiceWstEth contract V2 which supports rebalancing between AmmTreasury and AssetManagement. interface IAmmPoolsServiceWstEthBaseV2 is IAmmPoolsServiceWstEthBaseV1 { /// @notice Rebalances wstETH assets between the AmmTreasury and the AssetManagement, based on configuration stored /// in the `AmmPoolsParamsValue.ammTreasuryAndAssetManagementRatio` field. diff --git a/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol b/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol index 098d2e9d9..0e50bbcac 100644 --- a/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol @@ -194,7 +194,7 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { ipToken: ipToken, ammStorage: ammStorage, ammTreasury: ammTreasury, - assetManagement: address(0), + assetManagement: ammAssetManagement, iporOracle: iporOracle }); return model.getExchangeRate(actualLiquidityPoolBalance); diff --git a/scripts/LocalDeployment.s.sol b/scripts/LocalDeployment.s.sol deleted file mode 100644 index 388f316d9..000000000 --- a/scripts/LocalDeployment.s.sol +++ /dev/null @@ -1,882 +0,0 @@ -pragma solidity 0.8.26; - -import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -import "forge-std/Script.sol"; -import "../contracts/chains/ethereum/router/IporProtocolRouter.sol"; -import "../contracts/amm/AmmPoolsLens.sol"; -import "../contracts/amm/AmmOpenSwapService.sol"; -import "../contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol"; -import "../contracts/chains/ethereum/amm-commons/AmmSwapsLens.sol"; -import "../contracts/amm/AssetManagementLens.sol"; -import "../contracts/amm/AmmCloseSwapService.sol"; -import "../contracts/amm/AmmPoolsService.sol"; -import "../contracts/oracles/IporOracle.sol"; -import "../contracts/oracles/OraclePublisher.sol"; -import "../contracts/amm/spread/SpreadRouter.sol"; -import "../test/utils/TestConstants.sol"; -import "../contracts/amm/spread/SpreadStorageLens.sol"; -import "../contracts/amm/spread/Spread28Days.sol"; -import "../contracts/amm/spread/Spread60Days.sol"; -import "../contracts/amm/spread/Spread90Days.sol"; - -import "../contracts/vault/AssetManagementUsdt.sol"; -import "../contracts/vault/AssetManagementUsdc.sol"; -import "../contracts/vault/AssetManagementDai.sol"; -import "../contracts/tokens/IpToken.sol"; -import "../contracts/tokens/IvToken.sol"; -import "../test/mocks/tokens/MockTestnetToken.sol"; -import "../contracts/amm/AmmStorage.sol"; -import "../contracts/amm/AmmTreasury.sol"; -import "../contracts/amm/spread/SpreadCloseSwapService.sol"; -import "../test/mocks/TestnetFaucet.sol"; -import "../contracts/tokens/IporToken.sol"; - -import "../test/mocks/assetManagement/MockTestnetStrategy.sol"; -import "../contracts/amm/spread/SpreadStorageService.sol"; - -// run: -// $ anvil -// get private key from anvil then set SC_ADMIN_PRIV_KEY variable in .env file -// then run: -// $ forge script scripts/LocalDeployment.s.sol --fork-url http://127.0.0.1:8545 --broadcast -contract LocalDeployment is Script { - struct IporProtocol { - address asset; - address ipToken; - address ivToken; - address ammStorageProxy; - address ammStorageImpl; - address assetManagementProxy; - address assetManagementImpl; - address strategyAaveProxy; - address strategyAaveImpl; - address strategyCompoundProxy; - address strategyCompoundImpl; - address aToken; - address cToken; - address ammTreasuryProxy; - address ammTreasuryImpl; - } - - struct System { - address iporToken; - address routerProxy; - address routerImpl; - address spreadRouterProxy; - address spreadRouterImpl; - address iporOracleProxy; - address iporOracleImpl; - address oraclePublisherProxy; - address oraclePublisherImpl; - address ammSwapsLens; - address ammPoolsLens; - address assetManagementLens; - address ammOpenSwapService; - address ammCloseSwapService; - address riskOracleProxy; - address riskOracleImpl; - address ammPoolsService; - address ammGovernanceService; - address faucetProxy; - address faucetImpl; - IporProtocol usdt; - IporProtocol usdc; - IporProtocol dai; - } - - struct AmmConfig { - address oraclePublisherUpdater; - address powerTokenLens; - address liquidityMiningLens; - address flowService; - address stakeService; - } - - address defaultAnvilAddress = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; - uint256 _private_key; - string _env_profile; - AmmConfig ammConfig; - - function setUp() public { - _private_key = vm.envUint("SC_ADMIN_PRIV_KEY"); - _env_profile = vm.envString("ENV_PROFILE"); - ammConfig.oraclePublisherUpdater = vm.envAddress("SC_MIGRATION_ORACLE_UPDATER_ADDRESS"); - ammConfig.powerTokenLens = vm.envAddress("SC_POWER_TOKEN_LENS_ADDRESS"); - ammConfig.liquidityMiningLens = vm.envAddress("SC_LIQUIDITY_MINING_LENS_ADDRESS"); - ammConfig.flowService = vm.envAddress("SC_POWER_TOKEN_FLOW_SERVICE_ADDRESS"); - ammConfig.stakeService = vm.envAddress("SC_POWER_TOKEN_STAKE_SERVICE_ADDRESS"); - } - - function run() public { - System memory amm; - vm.startBroadcast(_private_key); - _getFullInstance(ammConfig, amm); - vm.stopBroadcast(); - _toAddressesJson(amm); - } - - function _getFullInstance(AmmConfig memory cfg, System memory system) public { - deployDummyIporProtocolRouter(system); - deployDummyAmmTreasury(system); - deployIporToken(system); - deployAssets(system); - deployOracle(system); - deployRiskOracle(system); - deployOraclePublisher(system); - deployIpTokens(system); - deployIvTokens(system); - deployStorage(system); - deploySpreadRouter(system); - deployAssetManagement(system); - upgradeAmmTreasury(system); - upgradeIporProtocolRouter(system); - } - - function _preparePoolCfgForGovernanceService( - address asset, - address ammTreasury, - address ammStorage - ) internal view returns (IAmmGovernanceLens.AmmGovernancePoolConfiguration memory poolCfg) { - poolCfg = IAmmGovernanceLens.AmmGovernancePoolConfiguration({ - asset: asset, - decimals: IERC20MetadataUpgradeable(asset).decimals(), - ammStorage: ammStorage, - ammTreasury: ammTreasury, - ammPoolsTreasury: asset, //TODO: fixit - ammPoolsTreasuryManager: asset, //TODO: fixit - ammCharlieTreasury: asset, //TODO: fixit - ammCharlieTreasuryManager: asset //TODO: fixit - }); - } - - function _preparePoolCfgForPoolsService( - address asset, - address ipToken, - address ammTreasury, - address ammStorage, - address assetManagement - ) internal view returns (IAmmPoolsService.AmmPoolsServicePoolConfiguration memory poolCfg) { - poolCfg = IAmmPoolsService.AmmPoolsServicePoolConfiguration({ - asset: asset, - decimals: IERC20MetadataUpgradeable(asset).decimals(), - ipToken: ipToken, - ammStorage: ammStorage, - ammTreasury: ammTreasury, - assetManagement: assetManagement, - redeemFeeRate: 5 * 1e15, - redeemLpMaxCollateralRatio: 1e18 - }); - } - - function _preparePoolCfgForCloseSwapService( - address asset, - address ammTreasury, - address ammStorage, - address assetManagement - ) internal view returns (IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg) { - poolCfg = IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration({ - asset: address(asset), - decimals: IERC20MetadataUpgradeable(asset).decimals(), - ammStorage: ammStorage, - ammTreasury: ammTreasury, - assetManagement: assetManagement, - unwindingFeeRate: 5e14, - unwindingFeeTreasuryPortionRate: 5e14, - maxLengthOfLiquidatedSwapsPerLeg: 10, - timeBeforeMaturityAllowedToCloseSwapByCommunity: 1 hours, - timeBeforeMaturityAllowedToCloseSwapByBuyer: 1 days, - minLiquidationThresholdToCloseBeforeMaturityByCommunity: 995 * 1e15, - minLiquidationThresholdToCloseBeforeMaturityByBuyer: 99 * 1e16, - minLeverage: 10 * 1e18 - }); - } - - function _preparePoolCfgForOpenSwapService( - address asset, - address ammTreasury, - address ammStorage - ) internal view returns (IAmmOpenSwapLens.AmmOpenSwapServicePoolConfiguration memory poolCfg) { - poolCfg = IAmmOpenSwapLens.AmmOpenSwapServicePoolConfiguration({ - asset: asset, - decimals: IERC20MetadataUpgradeable(asset).decimals(), - ammStorage: ammStorage, - ammTreasury: ammTreasury, - iporPublicationFee: 10 * 1e18, - maxSwapCollateralAmount: 100_000 * 1e18, - liquidationDepositAmount: 25, - minLeverage: 10 * 1e18, - openingFeeRate: 5e14, - openingFeeTreasuryPortionRate: 5e17 - }); - } - - function _getCurrentTimestamps( - address[] memory assets - ) internal view returns (uint32[] memory lastUpdateTimestamps) { - lastUpdateTimestamps = new uint32[](assets.length); - - uint32 lastUpdateTimestamp = uint32(block.timestamp); - - for (uint256 i = 0; i < assets.length; i++) { - lastUpdateTimestamps[i] = lastUpdateTimestamp; - } - } - - function deployOracle(System memory system) public { - address[] memory assets = new address[](3); - assets[0] = address(system.dai.asset); - assets[1] = address(system.usdt.asset); - assets[2] = address(system.usdc.asset); - - system.iporOracleImpl = address( - new IporOracle( - address(system.usdt.asset), - 1e18, - address(system.usdc.asset), - 1e18, - address(system.dai.asset), - 1e18 - ) - ); - - uint32[] memory lastUpdateTimestamps = _getCurrentTimestamps(assets); - - system.iporOracleProxy = address( - new ERC1967Proxy( - system.iporOracleImpl, - abi.encodeWithSignature("initialize(address[],uint32[])", assets, lastUpdateTimestamps) - ) - ); - } - - function deployRiskOracle(System memory system) public { - address[] memory assets = new address[](3); - assets[0] = address(system.dai.asset); - assets[1] = address(system.usdt.asset); - assets[2] = address(system.usdc.asset); - - IporRiskManagementOracleTypes.RiskIndicators[] - memory riskIndicators = new IporRiskManagementOracleTypes.RiskIndicators[](assets.length); - IporRiskManagementOracleTypes.BaseSpreadsAndFixedRateCaps[] - memory baseSpreadsAndFixedRateCaps = new IporRiskManagementOracleTypes.BaseSpreadsAndFixedRateCaps[]( - assets.length - ); - - for (uint256 i = 0; i < assets.length; i++) { - riskIndicators[i] = IporRiskManagementOracleTypes.RiskIndicators({ - maxNotionalPayFixed: TestConstants.RMO_NOTIONAL_1B, - maxNotionalReceiveFixed: TestConstants.RMO_NOTIONAL_1B, - maxCollateralRatioPayFixed: TestConstants.RMO_COLLATERAL_RATIO_48_PER, - maxCollateralRatioReceiveFixed: TestConstants.RMO_COLLATERAL_RATIO_48_PER, - maxCollateralRatio: TestConstants.RMO_COLLATERAL_RATIO_90_PER - }); - baseSpreadsAndFixedRateCaps[i] = IporRiskManagementOracleTypes.BaseSpreadsAndFixedRateCaps({ - spread28dPayFixed: TestConstants.RMO_SPREAD_0_1_PER, - spread28dReceiveFixed: TestConstants.RMO_SPREAD_0_1_PER, - spread60dPayFixed: TestConstants.RMO_SPREAD_0_1_PER, - spread60dReceiveFixed: TestConstants.RMO_SPREAD_0_1_PER, - spread90dPayFixed: TestConstants.RMO_SPREAD_0_1_PER, - spread90dReceiveFixed: TestConstants.RMO_SPREAD_0_1_PER, - fixedRateCap28dPayFixed: TestConstants.RMO_FIXED_RATE_CAP_2_0_PER, - fixedRateCap28dReceiveFixed: TestConstants.RMO_FIXED_RATE_CAP_3_5_PER, - fixedRateCap60dPayFixed: TestConstants.RMO_FIXED_RATE_CAP_2_0_PER, - fixedRateCap60dReceiveFixed: TestConstants.RMO_FIXED_RATE_CAP_3_5_PER, - fixedRateCap90dPayFixed: TestConstants.RMO_FIXED_RATE_CAP_2_0_PER, - fixedRateCap90dReceiveFixed: TestConstants.RMO_FIXED_RATE_CAP_3_5_PER - }); - } - - system.riskOracleImpl = address(new IporRiskManagementOracle()); - - system.riskOracleProxy = address( - address( - new ERC1967Proxy( - system.riskOracleImpl, - abi.encodeWithSignature( - "initialize(address[],(uint256,uint256,uint256,uint256,uint256)[],(int256,int256,int256,int256,int256,int256,uint256,uint256,uint256,uint256,uint256,uint256)[])", - assets, - riskIndicators, - baseSpreadsAndFixedRateCaps - ) - ) - ) - ); - } - - function deployOraclePublisher(System memory system) public { - system.oraclePublisherImpl = address(new OraclePublisher(system.iporOracleProxy, system.riskOracleProxy)); - - system.oraclePublisherProxy = address( - new ERC1967Proxy(system.oraclePublisherImpl, abi.encodeWithSignature("initialize()")) - ); - - IporOracle(system.iporOracleProxy).addUpdater(system.oraclePublisherProxy); - IporRiskManagementOracle(system.riskOracleProxy).addUpdater(system.oraclePublisherProxy); - OraclePublisher(system.oraclePublisherProxy).addUpdater(ammConfig.oraclePublisherUpdater); - } - - function deployDummyIporProtocolRouter(System memory system) public { - IporProtocolRouter.DeployedContracts memory deployedContracts = IporProtocolRouter.DeployedContracts({ - ammSwapsLens: defaultAnvilAddress, - ammPoolsLens: defaultAnvilAddress, - assetManagementLens: defaultAnvilAddress, - ammOpenSwapService: defaultAnvilAddress, - ammCloseSwapService: defaultAnvilAddress, - ammPoolsService: defaultAnvilAddress, - ammGovernanceService: defaultAnvilAddress, - liquidityMiningLens: defaultAnvilAddress, - powerTokenLens: defaultAnvilAddress, - flowService: defaultAnvilAddress, - stakeService: defaultAnvilAddress - }); - - system.routerImpl = address(new IporProtocolRouter(deployedContracts)); - - system.routerProxy = address( - new ERC1967Proxy(system.routerImpl, abi.encodeWithSignature("initialize(bool)", false)) - ); - } - - function deployIpTokens(System memory system) public { - system.usdt.ipToken = address(new IpToken("IP USDT", "ipUSDT", address(system.usdt.asset))); - system.usdc.ipToken = address(new IpToken("IP USDC", "ipUSDC", address(system.usdc.asset))); - system.dai.ipToken = address(new IpToken("IP DAI", "ipDAI", address(system.dai.asset))); - - IpToken(system.usdt.ipToken).setRouter(system.routerProxy); - IpToken(system.usdc.ipToken).setRouter(system.routerProxy); - IpToken(system.dai.ipToken).setRouter(system.routerProxy); - } - - function deployIvTokens(System memory system) public { - system.usdt.ivToken = address(new IvToken("IV USDT", "ivUSDT", system.usdt.asset)); - system.usdc.ivToken = address(new IvToken("IV USDC", "ivUSDC", system.usdc.asset)); - system.dai.ivToken = address(new IvToken("IV DAI", "ivDAI", system.dai.asset)); - } - - function deployAssets(System memory system) public { - system.usdt.asset = address( - new MockTestnetToken("Mocked USDT", "USDT", TestConstants.TOTAL_SUPPLY_6_DECIMALS, 6) - ); - system.usdc.asset = address( - new MockTestnetToken("Mocked USDC", "USDC", TestConstants.TOTAL_SUPPLY_6_DECIMALS, 6) - ); - system.dai.asset = address( - new MockTestnetToken("Mocked DAI", "DAI", TestConstants.TOTAL_SUPPLY_18_DECIMALS, 18) - ); - } - - function deployDummyAmmTreasury(System memory system) public { - AmmTreasury emptyImpl = new AmmTreasury( - defaultAnvilAddress, - 0, - defaultAnvilAddress, - defaultAnvilAddress, - defaultAnvilAddress - ); - - system.usdt.ammTreasuryProxy = address( - new ERC1967Proxy(address(emptyImpl), abi.encodeWithSignature("initialize(bool)", false)) - ); - - system.usdc.ammTreasuryProxy = address( - new ERC1967Proxy(address(emptyImpl), abi.encodeWithSignature("initialize(bool)", false)) - ); - - system.dai.ammTreasuryProxy = address( - new ERC1967Proxy(address(emptyImpl), abi.encodeWithSignature("initialize(bool)", false)) - ); - } - - function deployStorage(System memory system) public { - system.usdt.ammStorageImpl = address( - new AmmStorage(address(system.routerProxy), address(system.usdt.ammTreasuryProxy)) - ); - system.usdt.ammStorageProxy = address( - new ERC1967Proxy(system.usdt.ammStorageImpl, abi.encodeWithSignature("initialize()", "")) - ); - - system.usdc.ammStorageImpl = address( - new AmmStorage(address(system.routerProxy), address(system.usdc.ammTreasuryProxy)) - ); - system.usdc.ammStorageProxy = address( - new ERC1967Proxy(system.usdc.ammStorageImpl, abi.encodeWithSignature("initialize()", "")) - ); - - system.dai.ammStorageImpl = address( - new AmmStorage(address(system.routerProxy), address(system.dai.ammTreasuryProxy)) - ); - system.dai.ammStorageProxy = address( - new ERC1967Proxy(system.dai.ammStorageImpl, abi.encodeWithSignature("initialize()", "")) - ); - } - - function deploySpreadRouter(System memory system) public { - SpreadRouter.DeployedContracts memory deployedContracts; - deployedContracts.iporProtocolRouter = address(system.routerProxy); - deployedContracts.storageLens = address(new SpreadStorageLens()); - deployedContracts.spread28Days = address( - new Spread28Days(address(system.dai.asset), address(system.usdc.asset), address(system.usdt.asset)) - ); - deployedContracts.spread60Days = address( - new Spread60Days(address(system.dai.asset), address(system.usdc.asset), address(system.usdt.asset)) - ); - deployedContracts.spread90Days = address( - new Spread90Days(address(system.dai.asset), address(system.usdc.asset), address(system.usdt.asset)) - ); - - deployedContracts.closeSwapService = address( - new SpreadCloseSwapService( - address(system.dai.asset), - address(system.usdc.asset), - address(system.usdt.asset) - ) - ); - - deployedContracts.storageService = address(new SpreadStorageService()); - system.spreadRouterImpl = address(new SpreadRouter(deployedContracts)); - system.spreadRouterProxy = address( - new ERC1967Proxy(system.spreadRouterImpl, abi.encodeWithSignature("initialize(bool)", false)) - ); - } - - function deployAssetManagement(System memory system) internal { - system.usdt.aToken = address(new MockTestnetToken("Mocked Share aUSDT", "aUSDT", 0, 6)); - system.usdc.aToken = address(new MockTestnetToken("Mocked Share aUSDC", "aUSDC", 0, 6)); - system.dai.aToken = address(new MockTestnetToken("Mocked Share aDAI", "aDAI", 0, 18)); - - system.usdt.cToken = address(new MockTestnetToken("Mocked Share cUSDT", "cUSDT", 0, 6)); - system.usdc.cToken = address(new MockTestnetToken("Mocked Share cUSDC", "cUSDC", 0, 6)); - system.dai.cToken = address(new MockTestnetToken("Mocked Share cDAI", "cDAI", 0, 18)); - - system.usdt.strategyAaveImpl = address(new MockTestnetStrategy()); - system.usdt.strategyAaveProxy = address( - new ERC1967Proxy( - system.usdt.strategyAaveImpl, - abi.encodeWithSignature("initialize(address,address)", system.usdt.asset, system.usdt.aToken) - ) - ); - - system.usdt.strategyCompoundImpl = address(new MockTestnetStrategy()); - system.usdt.strategyCompoundProxy = address( - new ERC1967Proxy( - system.usdt.strategyCompoundImpl, - abi.encodeWithSignature("initialize(address,address)", system.usdt.asset, system.usdt.cToken) - ) - ); - - system.usdc.strategyAaveImpl = address(new MockTestnetStrategy()); - system.usdc.strategyAaveProxy = address( - new ERC1967Proxy( - system.usdc.strategyAaveImpl, - abi.encodeWithSignature("initialize(address,address)", system.usdc.asset, system.usdc.aToken) - ) - ); - - system.usdc.strategyCompoundImpl = address(new MockTestnetStrategy()); - system.usdc.strategyCompoundProxy = address( - new ERC1967Proxy( - system.usdc.strategyCompoundImpl, - abi.encodeWithSignature("initialize(address,address)", system.usdc.asset, system.usdc.cToken) - ) - ); - - system.dai.strategyAaveImpl = address(new MockTestnetStrategy()); - system.dai.strategyAaveProxy = address( - new ERC1967Proxy( - system.dai.strategyAaveImpl, - abi.encodeWithSignature("initialize(address,address)", system.dai.asset, system.dai.aToken) - ) - ); - - system.dai.strategyCompoundImpl = address(new MockTestnetStrategy()); - system.dai.strategyCompoundProxy = address( - new ERC1967Proxy( - system.dai.strategyCompoundImpl, - abi.encodeWithSignature("initialize(address,address)", system.dai.asset, system.dai.cToken) - ) - ); - - system.usdt.assetManagementImpl = address(new AssetManagementUsdt()); - system.usdt.assetManagementProxy = address( - new ERC1967Proxy( - system.usdt.assetManagementImpl, - abi.encodeWithSignature( - "initialize(address,address,address,address)", - system.usdt.asset, - system.usdt.ivToken, - system.usdt.strategyAaveProxy, - system.usdt.strategyCompoundProxy - ) - ) - ); - - system.usdc.assetManagementImpl = address(new AssetManagementUsdc()); - system.usdc.assetManagementProxy = address( - new ERC1967Proxy( - system.usdc.assetManagementImpl, - abi.encodeWithSignature( - "initialize(address,address,address,address)", - system.usdc.asset, - system.usdc.ivToken, - system.usdc.strategyAaveProxy, - system.usdc.strategyCompoundProxy - ) - ) - ); - - system.dai.assetManagementImpl = address(new AssetManagementDai()); - system.dai.assetManagementProxy = address( - new ERC1967Proxy( - system.dai.assetManagementImpl, - abi.encodeWithSignature( - "initialize(address,address,address,address)", - system.dai.asset, - system.dai.ivToken, - system.dai.strategyAaveProxy, - system.dai.strategyCompoundProxy - ) - ) - ); - - IStrategy(system.usdt.strategyAaveProxy).setAssetManagement(system.usdt.assetManagementProxy); - IStrategy(system.usdc.strategyAaveProxy).setAssetManagement(system.usdc.assetManagementProxy); - IStrategy(system.dai.strategyAaveProxy).setAssetManagement(system.dai.assetManagementProxy); - - IStrategy(system.usdt.strategyCompoundProxy).setAssetManagement(system.usdt.assetManagementProxy); - IStrategy(system.usdc.strategyCompoundProxy).setAssetManagement(system.usdc.assetManagementProxy); - IStrategy(system.dai.strategyCompoundProxy).setAssetManagement(system.dai.assetManagementProxy); - } - - function upgradeAmmTreasury(System memory system) internal { - system.usdt.ammTreasuryImpl = address( - new AmmTreasury( - system.usdt.asset, - 6, - system.usdt.ammStorageProxy, - system.usdt.assetManagementProxy, - system.routerProxy - ) - ); - AmmTreasury(system.usdt.ammTreasuryProxy).upgradeTo(system.usdt.ammTreasuryImpl); - - system.usdc.ammTreasuryImpl = address( - new AmmTreasury( - system.usdc.asset, - 6, - system.usdc.ammStorageProxy, - system.usdc.assetManagementProxy, - system.routerProxy - ) - ); - AmmTreasury(system.usdc.ammTreasuryProxy).upgradeTo(system.usdc.ammTreasuryImpl); - - system.dai.ammTreasuryImpl = address( - new AmmTreasury( - system.dai.asset, - 18, - system.dai.ammStorageProxy, - system.dai.assetManagementProxy, - system.routerProxy - ) - ); - AmmTreasury(system.dai.ammTreasuryProxy).upgradeTo(system.dai.ammTreasuryImpl); - } - - function upgradeIporProtocolRouter(System memory system) internal { - system.ammSwapsLens = address( - new AmmSwapsLens( - IAmmSwapsLens.SwapLensPoolConfiguration({ - asset: address(system.usdt.asset), - ammStorage: address(system.usdt.ammStorageProxy), - ammTreasury: address(system.usdt.ammTreasuryProxy), - minLeverage: 10 * 1e18 - }), - IAmmSwapsLens.SwapLensPoolConfiguration({ - asset: address(system.usdc.asset), - ammStorage: address(system.usdc.ammStorageProxy), - ammTreasury: address(system.usdc.ammTreasuryProxy), - minLeverage: 10 * 1e18 - }), - IAmmSwapsLens.SwapLensPoolConfiguration({ - asset: address(system.dai.asset), - ammStorage: address(system.dai.ammStorageProxy), - ammTreasury: address(system.dai.ammTreasuryProxy), - minLeverage: 10 * 1e18 - }), - system.iporOracleProxy, - system.riskOracleProxy, - system.spreadRouterProxy - ) - ); - - system.ammPoolsLens = address( - new AmmPoolsLens( - IAmmPoolsLens.AmmPoolsLensPoolConfiguration({ - asset: address(system.usdt.asset), - decimals: 6, - ipToken: address(system.usdt.ipToken), - ammStorage: address(system.usdt.ammStorageProxy), - ammTreasury: address(system.usdt.ammTreasuryProxy), - assetManagement: address(system.usdt.assetManagementProxy) - }), - IAmmPoolsLens.AmmPoolsLensPoolConfiguration({ - asset: address(system.usdc.asset), - decimals: 6, - ipToken: address(system.usdc.ipToken), - ammStorage: address(system.usdc.ammStorageProxy), - ammTreasury: address(system.usdc.ammTreasuryProxy), - assetManagement: address(system.usdc.assetManagementProxy) - }), - IAmmPoolsLens.AmmPoolsLensPoolConfiguration({ - asset: address(system.dai.asset), - decimals: 18, - ipToken: address(system.dai.ipToken), - ammStorage: address(system.dai.ammStorageProxy), - ammTreasury: address(system.dai.ammTreasuryProxy), - assetManagement: address(system.dai.assetManagementProxy) - }), - address(system.iporOracleProxy) - ) - ); - - system.assetManagementLens = address( - new AssetManagementLens( - IAssetManagementLens.AssetManagementConfiguration({ - asset: system.usdt.asset, - decimals: 6, - assetManagement: system.usdt.assetManagementProxy, - ammTreasury: system.usdt.ammTreasuryProxy - }), - IAssetManagementLens.AssetManagementConfiguration({ - asset: system.usdc.asset, - decimals: 6, - assetManagement: system.usdc.assetManagementProxy, - ammTreasury: system.usdc.ammTreasuryProxy - }), - IAssetManagementLens.AssetManagementConfiguration({ - asset: system.dai.asset, - decimals: 18, - assetManagement: system.dai.assetManagementProxy, - ammTreasury: system.dai.ammTreasuryProxy - }) - ) - ); - - system.ammOpenSwapService = address( - new AmmOpenSwapService({ - usdtPoolCfg: _preparePoolCfgForOpenSwapService( - address(system.usdt.asset), - address(system.usdt.ammTreasuryProxy), - address(system.usdt.ammStorageProxy) - ), - usdcPoolCfg: _preparePoolCfgForOpenSwapService( - address(system.usdc.asset), - address(system.usdc.ammTreasuryProxy), - address(system.usdc.ammStorageProxy) - ), - daiPoolCfg: _preparePoolCfgForOpenSwapService( - address(system.dai.asset), - address(system.dai.ammTreasuryProxy), - address(system.dai.ammStorageProxy) - ), - iporOracle: system.iporOracleProxy, - iporRiskManagementOracle: system.riskOracleProxy, - spreadRouter: system.spreadRouterProxy - }) - ); - - system.ammCloseSwapService = address( - new AmmCloseSwapService({ - usdtPoolCfg: _preparePoolCfgForCloseSwapService( - address(system.usdt.asset), - address(system.usdt.ammTreasuryProxy), - address(system.usdt.ammStorageProxy), - address(system.usdt.assetManagementProxy) - ), - usdcPoolCfg: _preparePoolCfgForCloseSwapService( - address(system.usdc.asset), - address(system.usdc.ammTreasuryProxy), - address(system.usdc.ammStorageProxy), - address(system.usdc.assetManagementProxy) - ), - daiPoolCfg: _preparePoolCfgForCloseSwapService( - address(system.dai.asset), - address(system.dai.ammTreasuryProxy), - address(system.dai.ammStorageProxy), - address(system.dai.assetManagementProxy) - ), - iporOracle: address(system.iporOracleProxy), - iporRiskManagementOracle: address(system.riskOracleProxy), - spreadRouter: address(system.spreadRouterProxy) - }) - ); - - system.ammPoolsService = address( - new AmmPoolsService({ - usdtPoolCfg: _preparePoolCfgForPoolsService( - address(system.usdt.asset), - address(system.usdt.ipToken), - address(system.usdt.ammTreasuryProxy), - address(system.usdt.ammStorageProxy), - address(system.usdt.assetManagementProxy) - ), - usdcPoolCfg: _preparePoolCfgForPoolsService( - address(system.usdc.asset), - address(system.usdc.ipToken), - address(system.usdc.ammTreasuryProxy), - address(system.usdc.ammStorageProxy), - address(system.usdc.assetManagementProxy) - ), - daiPoolCfg: _preparePoolCfgForPoolsService( - address(system.dai.asset), - address(system.dai.ipToken), - address(system.dai.ammTreasuryProxy), - address(system.dai.ammStorageProxy), - address(system.dai.assetManagementProxy) - ), - iporOracle: address(system.iporOracleProxy) - }) - ); - - system.ammGovernanceService = address( - new AmmGovernanceService({ - usdtPoolCfg: _preparePoolCfgForGovernanceService( - address(system.usdt.asset), - address(system.usdt.ammTreasuryProxy), - address(system.usdt.ammStorageProxy) - ), - usdcPoolCfg: _preparePoolCfgForGovernanceService( - address(system.usdc.asset), - address(system.usdc.ammTreasuryProxy), - address(system.usdc.ammStorageProxy) - ), - daiPoolCfg: _preparePoolCfgForGovernanceService( - address(system.dai.asset), - address(system.dai.ammTreasuryProxy), - address(system.dai.ammStorageProxy) - ) - }) - ); - - IporProtocolRouter.DeployedContracts memory deployedContracts = IporProtocolRouter.DeployedContracts({ - ammSwapsLens: system.ammSwapsLens, - ammPoolsLens: system.ammPoolsLens, - assetManagementLens: system.assetManagementLens, - ammOpenSwapService: system.ammOpenSwapService, - ammCloseSwapService: system.ammCloseSwapService, - ammPoolsService: system.ammPoolsService, - ammGovernanceService: system.ammGovernanceService, - liquidityMiningLens: ammConfig.liquidityMiningLens, - powerTokenLens: ammConfig.powerTokenLens, - flowService: ammConfig.flowService, - stakeService: ammConfig.stakeService - }); - - system.routerImpl = address(new IporProtocolRouter(deployedContracts)); - IporProtocolRouter(system.routerProxy).upgradeTo(system.routerImpl); - } - - function deployFaucet(System memory system) internal { - system.faucetImpl = address(new TestnetFaucet()); - system.faucetProxy = address( - new ERC1967Proxy( - system.faucetImpl, - abi.encodeWithSignature( - "initialize(address,address,address,address)", - system.dai.asset, - system.usdc.asset, - system.usdt.asset, - system.iporToken - ) - ) - ); - } - - function deployIporToken(System memory system) internal { - system.iporToken = address(new IporToken("Ipor Token", "IPOR", defaultAnvilAddress)); - } - - function _toAddressesJson(System memory system) internal { - string memory path = vm.projectRoot(); - string memory addressesJson = ""; - - vm.serializeAddress(addressesJson, "USDT", system.usdt.asset); - vm.serializeAddress(addressesJson, "USDC", system.usdc.asset); - vm.serializeAddress(addressesJson, "DAI", system.dai.asset); - - vm.serializeAddress(addressesJson, "ipUSDT", system.usdt.ipToken); - vm.serializeAddress(addressesJson, "ipUSDC", system.usdc.ipToken); - vm.serializeAddress(addressesJson, "ipDAI", system.dai.ipToken); - - vm.serializeAddress(addressesJson, "ivUSDT", system.usdt.ivToken); - vm.serializeAddress(addressesJson, "ivUSDC", system.usdc.ivToken); - vm.serializeAddress(addressesJson, "ivDAI", system.dai.ivToken); - - vm.serializeAddress(addressesJson, "aUSDT", system.usdt.aToken); - vm.serializeAddress(addressesJson, "aUSDC", system.usdc.aToken); - vm.serializeAddress(addressesJson, "aDAI", system.dai.aToken); - - vm.serializeAddress(addressesJson, "cUSDT", system.usdt.cToken); - vm.serializeAddress(addressesJson, "cUSDC", system.usdc.cToken); - vm.serializeAddress(addressesJson, "cDAI", system.dai.cToken); - - vm.serializeAddress(addressesJson, "StrategyCompoundUsdtProxy", system.usdt.strategyCompoundProxy); - vm.serializeAddress(addressesJson, "StrategyCompoundUsdcProxy", system.usdc.strategyCompoundProxy); - vm.serializeAddress(addressesJson, "StrategyCompoundDaiProxy", system.dai.strategyCompoundProxy); - - vm.serializeAddress(addressesJson, "StrategyCompoundUsdtImpl", system.usdt.strategyCompoundImpl); - vm.serializeAddress(addressesJson, "StrategyCompoundUsdcImpl", system.usdc.strategyCompoundImpl); - vm.serializeAddress(addressesJson, "StrategyCompoundDaiImpl", system.dai.strategyCompoundImpl); - - vm.serializeAddress(addressesJson, "StrategyAaveUsdt", system.usdt.strategyAaveProxy); - vm.serializeAddress(addressesJson, "StrategyAaveUsdc", system.usdc.strategyAaveProxy); - vm.serializeAddress(addressesJson, "StrategyAaveDai", system.dai.strategyAaveProxy); - - vm.serializeAddress(addressesJson, "StrategyAaveUsdtImpl", system.usdt.strategyAaveImpl); - vm.serializeAddress(addressesJson, "StrategyAaveUsdcImpl", system.usdc.strategyAaveImpl); - vm.serializeAddress(addressesJson, "StrategyAaveDaiImpl", system.dai.strategyAaveImpl); - - vm.serializeAddress(addressesJson, "AmmStorageUsdtProxy", system.usdt.ammStorageProxy); - vm.serializeAddress(addressesJson, "AmmStorageUsdcProxy", system.usdc.ammStorageProxy); - vm.serializeAddress(addressesJson, "AmmStorageDaiProxy", system.dai.ammStorageProxy); - - vm.serializeAddress(addressesJson, "AmmStorageUsdtImpl", system.usdt.ammStorageImpl); - vm.serializeAddress(addressesJson, "AmmStorageUsdcImpl", system.usdc.ammStorageImpl); - vm.serializeAddress(addressesJson, "AmmStorageDaiImpl", system.dai.ammStorageImpl); - - vm.serializeAddress(addressesJson, "AssetManagementUsdtProxy", system.usdt.assetManagementProxy); - vm.serializeAddress(addressesJson, "AssetManagementUsdcProxy", system.usdc.assetManagementProxy); - vm.serializeAddress(addressesJson, "AssetManagementDaiProxy", system.dai.assetManagementProxy); - - vm.serializeAddress(addressesJson, "AssetManagementUsdtImpl", system.usdt.assetManagementImpl); - vm.serializeAddress(addressesJson, "AssetManagementUsdcImpl", system.usdc.assetManagementImpl); - vm.serializeAddress(addressesJson, "AssetManagementDaiImpl", system.dai.assetManagementImpl); - - vm.serializeAddress(addressesJson, "AmmTreasuryUsdtProxy", system.usdt.ammTreasuryProxy); - vm.serializeAddress(addressesJson, "AmmTreasuryUsdcProxy", system.usdc.ammTreasuryProxy); - vm.serializeAddress(addressesJson, "AmmTreasuryDaiProxy", system.dai.ammTreasuryProxy); - - vm.serializeAddress(addressesJson, "AmmTreasuryUsdtImpl", system.usdt.ammTreasuryImpl); - vm.serializeAddress(addressesJson, "AmmTreasuryUsdcImpl", system.usdc.ammTreasuryImpl); - vm.serializeAddress(addressesJson, "AmmTreasuryDaiImpl", system.dai.ammTreasuryImpl); - - vm.serializeAddress(addressesJson, "SpreadRouterProxy", system.spreadRouterProxy); - vm.serializeAddress(addressesJson, "IporOracleProxy", system.iporOracleProxy); - vm.serializeAddress(addressesJson, "IporRiskManagementOracleProxy", system.riskOracleProxy); - - vm.serializeAddress(addressesJson, "SpreadRouterImpl", system.spreadRouterImpl); - vm.serializeAddress(addressesJson, "IporOracleImpl", system.iporOracleImpl); - vm.serializeAddress(addressesJson, "IporRiskManagementOracleImpl", system.riskOracleImpl); - - vm.serializeAddress(addressesJson, "IporProtocolRouterProxy", system.routerProxy); - vm.serializeAddress(addressesJson, "IporProtocolRouterImpl", system.routerImpl); - - vm.serializeAddress(addressesJson, "IporToken", system.iporToken); - vm.serializeAddress(addressesJson, "FaucetImpl", system.faucetImpl); - vm.serializeAddress(addressesJson, "FaucetProxy", system.faucetProxy); - - string memory finalJson = vm.serializeAddress(addressesJson, "IporProtocolRouterProxy", system.routerProxy); - - vm.writeJson(finalJson, string.concat(path, "/.ipor/", _env_profile, "-ipor-protocol-addresses.json")); - } -} From ee881f84ea7e315dc3d8f679be3d539c2d6afc35 Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 22 May 2025 09:31:17 +0200 Subject: [PATCH 3/6] Unused code. --- contracts/amm/AmmCloseSwapServiceStable.sol | 2 -- contracts/amm/AmmPoolsService.sol | 1 - contracts/amm/libraries/SwapCloseLogicLib.sol | 2 -- contracts/amm/spread/Spread60Days.sol | 1 - contracts/amm/spread/Spread90Days.sol | 2 -- .../base/amm-usdc/services/AmmOpenSwapServiceUsdcBaseV1.sol | 2 -- .../amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV1.sol | 1 - contracts/base/amm/libraries/SwapCloseLogicLibBaseV1.sol | 2 -- contracts/base/amm/libraries/SwapLogicBaseV1.sol | 2 -- contracts/base/amm/services/AmmCloseSwapLensBaseV1.sol | 3 --- contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol | 1 - contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol | 1 - contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol | 1 - contracts/base/amm/services/AmmPoolsServiceBaseV1.sol | 2 -- contracts/base/spread/SpreadBaseV2.sol | 1 - .../chains/arbitrum/amm-commons/AmmCloseSwapLensArbitrum.sol | 3 --- .../arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol | 2 -- contracts/chains/arbitrum/amm-commons/AmmSwapsLensArbitrum.sol | 2 -- .../chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol | 1 - .../chains/arbitrum/router/IporProtocolRouterArbitrum.sol | 2 -- contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol | 3 --- contracts/router/IporProtocolRouterAbstract.sol | 2 -- contracts/tokens/IpToken.sol | 2 -- 23 files changed, 41 deletions(-) diff --git a/contracts/amm/AmmCloseSwapServiceStable.sol b/contracts/amm/AmmCloseSwapServiceStable.sol index 77c13ee84..46bb70a1b 100644 --- a/contracts/amm/AmmCloseSwapServiceStable.sol +++ b/contracts/amm/AmmCloseSwapServiceStable.sol @@ -15,7 +15,6 @@ import "../libraries/math/IporMath.sol"; import "../libraries/IporContractValidator.sol"; import "../libraries/AmmLib.sol"; import "../libraries/AssetManagementLogic.sol"; -import "../libraries/RiskIndicatorsValidatorLib.sol"; import "../libraries/AmmCloseSwapServicePoolConfigurationLib.sol"; import "../governance/AmmConfigurationManager.sol"; import "../base/amm/libraries/SwapLogicBaseV1.sol"; @@ -33,7 +32,6 @@ abstract contract AmmCloseSwapServiceStable is IAmmCloseSwapService { using SafeCast for int256; using SafeERC20Upgradeable for IERC20Upgradeable; using AmmLib for AmmTypes.AmmPoolCoreModel; - using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; using AmmCloseSwapServicePoolConfigurationLib for IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration; address internal immutable _asset; diff --git a/contracts/amm/AmmPoolsService.sol b/contracts/amm/AmmPoolsService.sol index 8351309ad..7073de8d1 100644 --- a/contracts/amm/AmmPoolsService.sol +++ b/contracts/amm/AmmPoolsService.sol @@ -24,7 +24,6 @@ contract AmmPoolsService is IAmmPoolsService { using IporContractValidator for address; using SafeCast for int256; using SafeCast for uint256; - using SafeCast for uint32; using SafeERC20Upgradeable for IERC20Upgradeable; using AmmLib for AmmTypes.AmmPoolCoreModel; diff --git a/contracts/amm/libraries/SwapCloseLogicLib.sol b/contracts/amm/libraries/SwapCloseLogicLib.sol index a43c9ae9e..027de4176 100644 --- a/contracts/amm/libraries/SwapCloseLogicLib.sol +++ b/contracts/amm/libraries/SwapCloseLogicLib.sol @@ -9,9 +9,7 @@ import "../../base/amm/libraries/SwapCloseLogicLibBaseV1.sol"; library SwapCloseLogicLib { using SafeCast for uint256; - using SafeCast for int256; using InterestRates for uint256; - using InterestRates for int256; using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; /// @notice Calculate swap unwind when unwind is required. diff --git a/contracts/amm/spread/Spread60Days.sol b/contracts/amm/spread/Spread60Days.sol index 99ec8d951..94b302ca2 100644 --- a/contracts/amm/spread/Spread60Days.sol +++ b/contracts/amm/spread/Spread60Days.sol @@ -13,7 +13,6 @@ import "../../amm/spread/OfferedRateCalculationLibs.sol"; /// @dev This contract cannot be used directly, should be used only through SpreadRouter. contract Spread60Days is ISpread60Days, ISpread60DaysLens { using IporContractValidator for address; - using SafeCast for uint256; using SafeCast for int256; address internal immutable _dai; diff --git a/contracts/amm/spread/Spread90Days.sol b/contracts/amm/spread/Spread90Days.sol index 47269f046..3582ef967 100644 --- a/contracts/amm/spread/Spread90Days.sol +++ b/contracts/amm/spread/Spread90Days.sol @@ -13,8 +13,6 @@ import "../../amm/spread/OfferedRateCalculationLibs.sol"; /// @dev This contract cannot be used directly, should be used only through SpreadRouter. contract Spread90Days is ISpread90Days, ISpread90DaysLens { using IporContractValidator for address; - using SafeCast for uint256; - using SafeCast for int256; address internal immutable _dai; address internal immutable _usdc; diff --git a/contracts/base/amm-usdc/services/AmmOpenSwapServiceUsdcBaseV1.sol b/contracts/base/amm-usdc/services/AmmOpenSwapServiceUsdcBaseV1.sol index ca5841882..080c27b74 100644 --- a/contracts/base/amm-usdc/services/AmmOpenSwapServiceUsdcBaseV1.sol +++ b/contracts/base/amm-usdc/services/AmmOpenSwapServiceUsdcBaseV1.sol @@ -9,7 +9,6 @@ import {IporTypes} from "../../../interfaces/types/IporTypes.sol"; import {AmmTypes} from "../../../interfaces/types/AmmTypes.sol"; import {IporErrors} from "../../../libraries/errors/IporErrors.sol"; import {IporMath} from "../../../libraries/math/IporMath.sol"; -import {IporContractValidator} from "../../../libraries/IporContractValidator.sol"; import {IAmmOpenSwapServiceUsdcBaseV1} from "../interfaces/IAmmOpenSwapServiceUsdcBaseV1.sol"; import {AmmTypesBaseV1} from "../../../base/types/AmmTypesBaseV1.sol"; import {AmmOpenSwapServiceBaseV1} from "../../../base/amm/services/AmmOpenSwapServiceBaseV1.sol"; @@ -19,7 +18,6 @@ import {StorageLibBaseV1} from "../../libraries/StorageLibBaseV1.sol"; /// @dev Service can be safely used directly only if you are sure that methods will not touch any storage variables. contract AmmOpenSwapServiceUsdcBaseV1 is AmmOpenSwapServiceBaseV1, IAmmOpenSwapServiceUsdcBaseV1 { using SafeERC20Upgradeable for IERC20Upgradeable; - using IporContractValidator for address; modifier onlySupportedInputAsset(address inputAsset) { if (inputAsset == asset) { diff --git a/contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV1.sol b/contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV1.sol index ca21c2cf3..c6957f859 100644 --- a/contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV1.sol +++ b/contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV1.sol @@ -9,7 +9,6 @@ import {StorageLibBaseV1} from "../../libraries/StorageLibBaseV1.sol"; /// @dev Service can be safely used directly only if you are sure that methods will not touch any storage variables. /// @dev Close Swap Service for wstEth pool - Asset Management IS NOT supported in this contract. contract AmmCloseSwapServiceWstEthBaseV1 is AmmCloseSwapServiceBaseV1, IAmmCloseSwapServiceWstEth { - using IporContractValidator for address; constructor( IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg, diff --git a/contracts/base/amm/libraries/SwapCloseLogicLibBaseV1.sol b/contracts/base/amm/libraries/SwapCloseLogicLibBaseV1.sol index 1e05ce9b4..9de81e757 100644 --- a/contracts/base/amm/libraries/SwapCloseLogicLibBaseV1.sol +++ b/contracts/base/amm/libraries/SwapCloseLogicLibBaseV1.sol @@ -15,8 +15,6 @@ import "./SwapLogicBaseV1.sol"; library SwapCloseLogicLibBaseV1 { using SafeCast for uint256; - using SafeCast for int256; - using InterestRates for uint256; using InterestRates for int256; using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; diff --git a/contracts/base/amm/libraries/SwapLogicBaseV1.sol b/contracts/base/amm/libraries/SwapLogicBaseV1.sol index aa5414ab2..96243a817 100644 --- a/contracts/base/amm/libraries/SwapLogicBaseV1.sol +++ b/contracts/base/amm/libraries/SwapLogicBaseV1.sol @@ -12,10 +12,8 @@ import "../../types/AmmTypesBaseV1.sol"; /// @title Core logic for IPOR Swap library SwapLogicBaseV1 { using SafeCast for uint256; - using SafeCast for int256; using InterestRates for uint256; using InterestRates for int256; - using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; /// @notice Calculates core amounts related with swap /// @param tenor swap duration, 0 = 28 days, 1 = 60 days, 2 = 90 days diff --git a/contracts/base/amm/services/AmmCloseSwapLensBaseV1.sol b/contracts/base/amm/services/AmmCloseSwapLensBaseV1.sol index 7c7f2f9d2..dde960779 100644 --- a/contracts/base/amm/services/AmmCloseSwapLensBaseV1.sol +++ b/contracts/base/amm/services/AmmCloseSwapLensBaseV1.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; - import "../../../interfaces/types/IporTypes.sol"; import "../../../interfaces/types/AmmTypes.sol"; import "../../../interfaces/IIporOracle.sol"; @@ -18,7 +16,6 @@ import {StorageLibBaseV1} from "../../libraries/StorageLibBaseV1.sol"; /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. contract AmmCloseSwapLensBaseV1 is IAmmCloseSwapLens { - using Address for address; using IporContractValidator for address; using SwapLogicBaseV1 for AmmTypesBaseV1.Swap; using AmmCloseSwapServicePoolConfigurationLib for IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration; diff --git a/contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol b/contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol index e8157042b..061b3ece9 100644 --- a/contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol @@ -30,7 +30,6 @@ abstract contract AmmCloseSwapServiceBaseV1 is IAmmCloseSwapService { using SafeERC20Upgradeable for IERC20Upgradeable; using SwapLogicBaseV1 for AmmTypesBaseV1.Swap; using AmmLib for AmmTypes.AmmPoolCoreModel; - using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; address public immutable asset; uint256 public immutable decimals; diff --git a/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol b/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol index f78410df4..4eba63cd6 100644 --- a/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol +++ b/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol @@ -27,7 +27,6 @@ import {AssetManagementLogic} from "../../../libraries/AssetManagementLogic.sol" /// @title Abstract contract for closing swap, generation one, /// characterized by: with additional asset management logic and rebalance between AmmTreasury and Asset Management (PlasmaVault from Ipor Fusion) abstract contract AmmCloseSwapServiceBaseV2 is AmmCloseSwapServiceBaseV1 { - using Address for address; using IporContractValidator for address; using SafeCast for int256; using SafeERC20Upgradeable for IERC20Upgradeable; diff --git a/contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol b/contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol index a983a8487..c9619471c 100644 --- a/contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol @@ -22,7 +22,6 @@ contract AmmGovernanceServiceBaseV1 is IAmmGovernanceLens, IAmmGovernanceLensBaseV1 { - using IporContractValidator for address; using SafeERC20Upgradeable for IERC20Upgradeable; modifier onlySupportedAssetManagement(address asset) { diff --git a/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol b/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol index 0e50bbcac..24454c320 100644 --- a/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol @@ -29,8 +29,6 @@ import "../../../governance/AmmConfigurationManager.sol"; contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { using IporContractValidator for address; using SafeCast for int256; - using SafeCast for uint256; - using SafeCast for uint32; using SafeERC20Upgradeable for IERC20Upgradeable; using AmmLib for AmmTypes.AmmPoolCoreModel; diff --git a/contracts/base/spread/SpreadBaseV2.sol b/contracts/base/spread/SpreadBaseV2.sol index 3958b3f7e..c86a861c9 100644 --- a/contracts/base/spread/SpreadBaseV2.sol +++ b/contracts/base/spread/SpreadBaseV2.sol @@ -26,7 +26,6 @@ abstract contract SpreadBaseV2 is IporOwnable, ISpreadBaseV1 { error UnknownTenor(IporTypes.SwapTenor tenor, string errorCode, string methodName); using IporContractValidator for address; using SafeCast for uint256; - using SafeCast for int256; address public immutable asset; address public immutable iporProtocolRouter; diff --git a/contracts/chains/arbitrum/amm-commons/AmmCloseSwapLensArbitrum.sol b/contracts/chains/arbitrum/amm-commons/AmmCloseSwapLensArbitrum.sol index 719e87b2c..5c065eccd 100644 --- a/contracts/chains/arbitrum/amm-commons/AmmCloseSwapLensArbitrum.sol +++ b/contracts/chains/arbitrum/amm-commons/AmmCloseSwapLensArbitrum.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; - import "../../../interfaces/types/IporTypes.sol"; import "../../../interfaces/types/AmmTypes.sol"; import "../../../interfaces/IIporOracle.sol"; @@ -18,7 +16,6 @@ import {StorageLibArbitrum} from "../libraries/StorageLibArbitrum.sol"; /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. contract AmmCloseSwapLensArbitrum is IAmmCloseSwapLens { - using Address for address; using IporContractValidator for address; using SwapLogicBaseV1 for AmmTypesBaseV1.Swap; using AmmCloseSwapServicePoolConfigurationLib for IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration; diff --git a/contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol b/contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol index 9d02374e7..b61aee972 100644 --- a/contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol +++ b/contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol @@ -9,7 +9,6 @@ import "../../../interfaces/IAmmGovernanceService.sol"; import "../../../interfaces/IAmmGovernanceLens.sol"; import "../../../libraries/math/IporMath.sol"; import "../../../libraries/errors/AmmPoolsErrors.sol"; -import "../../../libraries/IporContractValidator.sol"; import "../../../governance/AmmConfigurationManager.sol"; import {StorageLibArbitrum} from "../libraries/StorageLibArbitrum.sol"; import {IAmmGovernanceServiceArbitrum} from "../interfaces/IAmmGovernanceServiceArbitrum.sol"; @@ -22,7 +21,6 @@ contract AmmGovernanceServiceArbitrum is IAmmGovernanceLens, IAmmGovernanceLensArbitrum { - using IporContractValidator for address; using SafeERC20Upgradeable for IERC20Upgradeable; modifier onlySupportedAssetManagement(address asset) { diff --git a/contracts/chains/arbitrum/amm-commons/AmmSwapsLensArbitrum.sol b/contracts/chains/arbitrum/amm-commons/AmmSwapsLensArbitrum.sol index 8bd33a584..451a7a654 100644 --- a/contracts/chains/arbitrum/amm-commons/AmmSwapsLensArbitrum.sol +++ b/contracts/chains/arbitrum/amm-commons/AmmSwapsLensArbitrum.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; import "../../../interfaces/IAmmSwapsLens.sol"; import "../../../base/amm/libraries/AmmSwapsLensLibBaseV1.sol"; import "../../../libraries/IporContractValidator.sol"; @@ -11,7 +10,6 @@ import {StorageLibArbitrum} from "../libraries/StorageLibArbitrum.sol"; /// @dev It is not recommended to use lens contract directly, should be used only through IporProtocolRouter. contract AmmSwapsLensArbitrum is IAmmSwapsLens { - using Address for address; using IporContractValidator for address; using AmmLib for AmmTypes.AmmPoolCoreModel; using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; diff --git a/contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol b/contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol index 02efa0a97..cc0d3797a 100644 --- a/contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol +++ b/contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol @@ -10,7 +10,6 @@ import {StorageLibArbitrum} from "../libraries/StorageLibArbitrum.sol"; /// @dev Service can be safely used directly only if you are sure that methods will not touch any storage variables. contract AmmOpenSwapServiceWstEth is AmmOpenSwapServiceBaseV1, IAmmOpenSwapServiceWstEth { using SafeERC20Upgradeable for IERC20Upgradeable; - using IporContractValidator for address; modifier onlySupportedInputAsset(address inputAsset) { if (inputAsset == asset) { diff --git a/contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol b/contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol index c78a38bf0..00d2e4426 100644 --- a/contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol +++ b/contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {IPowerTokenLens} from "../../../interfaces/IPowerTokenLens.sol"; import {IPowerTokenFlowsService} from "../../../interfaces/IPowerTokenFlowsService.sol"; import {ILiquidityMiningLens} from "../../../interfaces/ILiquidityMiningLens.sol"; @@ -27,7 +26,6 @@ import {IporProtocolRouterAbstract} from "../../../router/IporProtocolRouterAbst /// @title Entry point for IPOR protocol contract IporProtocolRouterArbitrum is IporProtocolRouterAbstract { - using Address for address; using IporContractValidator for address; address public immutable ammSwapsLens; diff --git a/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol b/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol index 73c468d8f..a7eba2dc8 100644 --- a/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol +++ b/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; - import "../../../interfaces/types/IporTypes.sol"; import "../../../interfaces/types/AmmTypes.sol"; import "../../../interfaces/IIporOracle.sol"; @@ -19,7 +17,6 @@ import "../../../base/amm/services/AmmCloseSwapServiceBaseV1.sol"; /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. contract AmmCloseSwapLens is IAmmCloseSwapLens { - using Address for address; using IporContractValidator for address; using SwapLogicBaseV1 for AmmTypesBaseV1.Swap; using AmmCloseSwapServicePoolConfigurationLib for IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration; diff --git a/contracts/router/IporProtocolRouterAbstract.sol b/contracts/router/IporProtocolRouterAbstract.sol index 1ef166fac..a446cfe40 100644 --- a/contracts/router/IporProtocolRouterAbstract.sol +++ b/contracts/router/IporProtocolRouterAbstract.sol @@ -5,7 +5,6 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {IProxyImplementation} from "../interfaces/IProxyImplementation.sol"; import {IporErrors} from "../libraries/errors/IporErrors.sol"; -import {IporContractValidator} from "../libraries/IporContractValidator.sol"; import {AccessControl} from "./AccessControl.sol"; import {StorageLib} from "../libraries/StorageLib.sol"; import {OwnerManager} from "../security/OwnerManager.sol"; @@ -14,7 +13,6 @@ import {StorageSlotUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ /// @title Entry point for IPOR protocol abstract contract IporProtocolRouterAbstract is UUPSUpgradeable, AccessControl, IProxyImplementation { using Address for address; - using IporContractValidator for address; uint256 private constant SINGLE_OPERATION = 0; uint256 private constant BATCH_OPERATION = 1; diff --git a/contracts/tokens/IpToken.sol b/contracts/tokens/IpToken.sol index 4ebb98f7a..5fba45ebb 100644 --- a/contracts/tokens/IpToken.sol +++ b/contracts/tokens/IpToken.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "../interfaces/IIpToken.sol"; import "../libraries/errors/IporErrors.sol"; @@ -10,7 +9,6 @@ import "../libraries/errors/AmmPoolsErrors.sol"; import "../security/IporOwnable.sol"; contract IpToken is IporOwnable, IIpToken, ERC20 { - using SafeERC20 for IERC20; address private immutable _asset; From b4b591065e89bda2acfaa073969232341067c211 Mon Sep 17 00:00:00 2001 From: Mario Date: Thu, 22 May 2025 16:15:44 +0200 Subject: [PATCH 4/6] Unused code. --- contracts/amm/AmmCloseSwapServiceStable.sol | 2 -- contracts/amm/AmmPoolsService.sol | 1 - contracts/amm/AmmTreasury.sol | 1 - contracts/amm/AssetManagementLens.sol | 1 - .../amm/libraries/SoapIndicatorRebalanceLogic.sol | 2 -- contracts/amm/libraries/SwapCloseLogicLib.sol | 2 -- contracts/amm/spread/Spread28Days.sol | 2 -- contracts/amm/spread/Spread60Days.sol | 1 - contracts/amm/spread/SpreadCloseSwapService.sol | 1 - .../amm-usdc/services/AmmPoolsServiceUsdcBaseV1.sol | 9 --------- .../services/AmmCloseSwapServiceWstEthBaseV2.sol | 3 --- .../services/AmmOpenSwapServiceWstEthBaseV1.sol | 1 - contracts/base/amm/AmmStorageBaseV1.sol | 1 - contracts/base/amm/libraries/SwapLogicBaseV1.sol | 1 - .../base/amm/services/AmmCloseSwapServiceBaseV1.sol | 7 ------- .../base/amm/services/AmmCloseSwapServiceBaseV2.sol | 3 --- .../base/amm/services/AmmOpenSwapServiceBaseV1.sol | 2 -- contracts/base/amm/services/AmmPoolsServiceBaseV1.sol | 4 ---- contracts/base/amm/services/AmmSwapsLensBaseV1.sol | 2 -- contracts/base/spread/SpreadBaseV1.sol | 1 - contracts/base/spread/SpreadBaseV2.sol | 2 -- .../chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol | 10 ---------- .../arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol | 1 - .../chains/base/router/IporProtocolRouterBase.sol | 2 -- .../chains/ethereum/router/IporProtocolRouter.sol | 3 --- contracts/interfaces/IAssetManagement.sol | 4 ---- contracts/libraries/AmmLib.sol | 1 - contracts/libraries/errors/IporErrors.sol | 3 --- 28 files changed, 73 deletions(-) diff --git a/contracts/amm/AmmCloseSwapServiceStable.sol b/contracts/amm/AmmCloseSwapServiceStable.sol index 46bb70a1b..5f2852bf9 100644 --- a/contracts/amm/AmmCloseSwapServiceStable.sol +++ b/contracts/amm/AmmCloseSwapServiceStable.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "../interfaces/types/IporTypes.sol"; @@ -26,7 +25,6 @@ import "./libraries/SwapCloseLogicLib.sol"; /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. abstract contract AmmCloseSwapServiceStable is IAmmCloseSwapService { - using Address for address; using IporContractValidator for address; using SafeCast for uint256; using SafeCast for int256; diff --git a/contracts/amm/AmmPoolsService.sol b/contracts/amm/AmmPoolsService.sol index 7073de8d1..51b473ae3 100644 --- a/contracts/amm/AmmPoolsService.sol +++ b/contracts/amm/AmmPoolsService.sol @@ -23,7 +23,6 @@ import "../governance/AmmConfigurationManager.sol"; contract AmmPoolsService is IAmmPoolsService { using IporContractValidator for address; using SafeCast for int256; - using SafeCast for uint256; using SafeERC20Upgradeable for IERC20Upgradeable; using AmmLib for AmmTypes.AmmPoolCoreModel; diff --git a/contracts/amm/AmmTreasury.sol b/contracts/amm/AmmTreasury.sol index d03aa08d6..71fc44dbb 100644 --- a/contracts/amm/AmmTreasury.sol +++ b/contracts/amm/AmmTreasury.sol @@ -11,7 +11,6 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {IporMath} from "../libraries/math/IporMath.sol"; import "../interfaces/IAmmTreasury.sol"; import "../interfaces/IAmmStorage.sol"; -import "../interfaces/IAssetManagement.sol"; import "../interfaces/IProxyImplementation.sol"; import "../interfaces/IIporContractCommonGov.sol"; import "../libraries/Constants.sol"; diff --git a/contracts/amm/AssetManagementLens.sol b/contracts/amm/AssetManagementLens.sol index 69eb7b527..96fce0e51 100644 --- a/contracts/amm/AssetManagementLens.sol +++ b/contracts/amm/AssetManagementLens.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.26; import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol"; import "../interfaces/IAssetManagementLens.sol"; -import "../interfaces/IAssetManagement.sol"; import "../libraries/errors/IporErrors.sol"; import {IporMath} from "../libraries/math/IporMath.sol"; import "../libraries/IporContractValidator.sol"; diff --git a/contracts/amm/libraries/SoapIndicatorRebalanceLogic.sol b/contracts/amm/libraries/SoapIndicatorRebalanceLogic.sol index 06c30cb69..47306619e 100644 --- a/contracts/amm/libraries/SoapIndicatorRebalanceLogic.sol +++ b/contracts/amm/libraries/SoapIndicatorRebalanceLogic.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "../../interfaces/types/AmmStorageTypes.sol"; import "../../libraries/errors/AmmErrors.sol"; import "../../libraries/math/IporMath.sol"; @@ -9,7 +8,6 @@ import "../../amm/libraries/SoapIndicatorLogic.sol"; /// @title Basic logic related with SOAP indicators when rebalance library SoapIndicatorRebalanceLogic { - using SafeCast for uint256; using InterestRates for uint256; /// @notice Update SOAP indicators when open swap diff --git a/contracts/amm/libraries/SwapCloseLogicLib.sol b/contracts/amm/libraries/SwapCloseLogicLib.sol index 027de4176..df08fac0d 100644 --- a/contracts/amm/libraries/SwapCloseLogicLib.sol +++ b/contracts/amm/libraries/SwapCloseLogicLib.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; import "../../interfaces/types/AmmTypes.sol"; -import "../../libraries/math/InterestRates.sol"; import "../../libraries/RiskManagementLogic.sol"; import "../../libraries/RiskIndicatorsValidatorLib.sol"; import "../../base/amm/libraries/SwapLogicBaseV1.sol"; @@ -9,7 +8,6 @@ import "../../base/amm/libraries/SwapCloseLogicLibBaseV1.sol"; library SwapCloseLogicLib { using SafeCast for uint256; - using InterestRates for uint256; using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; /// @notice Calculate swap unwind when unwind is required. diff --git a/contracts/amm/spread/Spread28Days.sol b/contracts/amm/spread/Spread28Days.sol index 4fc63c881..fc47be1eb 100644 --- a/contracts/amm/spread/Spread28Days.sol +++ b/contracts/amm/spread/Spread28Days.sol @@ -13,8 +13,6 @@ import "../../amm/spread/OfferedRateCalculationLibs.sol"; /// @dev This contract cannot be used directly, should be used only through SpreadRouter. contract Spread28Days is ISpread28Days, ISpread28DaysLens { using IporContractValidator for address; - using SafeCast for uint256; - using SafeCast for int256; address internal immutable _dai; address internal immutable _usdc; diff --git a/contracts/amm/spread/Spread60Days.sol b/contracts/amm/spread/Spread60Days.sol index 94b302ca2..030789d13 100644 --- a/contracts/amm/spread/Spread60Days.sol +++ b/contracts/amm/spread/Spread60Days.sol @@ -13,7 +13,6 @@ import "../../amm/spread/OfferedRateCalculationLibs.sol"; /// @dev This contract cannot be used directly, should be used only through SpreadRouter. contract Spread60Days is ISpread60Days, ISpread60DaysLens { using IporContractValidator for address; - using SafeCast for int256; address internal immutable _dai; address internal immutable _usdc; diff --git a/contracts/amm/spread/SpreadCloseSwapService.sol b/contracts/amm/spread/SpreadCloseSwapService.sol index f9c5bf909..7de46a1cf 100644 --- a/contracts/amm/spread/SpreadCloseSwapService.sol +++ b/contracts/amm/spread/SpreadCloseSwapService.sol @@ -14,7 +14,6 @@ import "../../base/amm/libraries/SwapLogicBaseV1.sol"; /// @dev It is not recommended to use service contract directly, should be used only through SpreadRouter. contract SpreadCloseSwapService is ISpreadCloseSwapService { using IporContractValidator for address; - using SafeCast for uint256; address internal immutable _dai; address internal immutable _usdc; diff --git a/contracts/base/amm-usdc/services/AmmPoolsServiceUsdcBaseV1.sol b/contracts/base/amm-usdc/services/AmmPoolsServiceUsdcBaseV1.sol index 2bea7e7f9..8bd3d1bf5 100644 --- a/contracts/base/amm-usdc/services/AmmPoolsServiceUsdcBaseV1.sol +++ b/contracts/base/amm-usdc/services/AmmPoolsServiceUsdcBaseV1.sol @@ -1,18 +1,9 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.26; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import "../../../interfaces/IIpToken.sol"; -import "../../../interfaces/types/AmmTypes.sol"; -import "../../../libraries/errors/AmmErrors.sol"; -import "../../../libraries/math/IporMath.sol"; -import "../../../libraries/IporContractValidator.sol"; import "../../../libraries/AmmLib.sol"; -import "../../../governance/AmmConfigurationManager.sol"; -import "../../../base/interfaces/IAmmTreasuryBaseV1.sol"; import {IAmmPoolsServiceUsdcBaseV1} from "../interfaces/IAmmPoolsServiceUsdcBaseV1.sol"; import {AmmPoolsServiceBaseV1} from "../../../base/amm/services/AmmPoolsServiceBaseV1.sol"; diff --git a/contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV2.sol b/contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV2.sol index 8ba0be38b..4f7bb6e23 100644 --- a/contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV2.sol +++ b/contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV2.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.26; import {IAmmCloseSwapServiceWstEth} from "../../../interfaces/IAmmCloseSwapServiceWstEth.sol"; import {AmmCloseSwapServiceBaseV2} from "../../../base/amm/services/AmmCloseSwapServiceBaseV2.sol"; import {StorageLibBaseV1} from "../../libraries/StorageLibBaseV1.sol"; -import {IporContractValidator} from "../../../libraries/IporContractValidator.sol"; import {AmmTypes} from "../../../interfaces/types/AmmTypes.sol"; import {IAmmCloseSwapLens} from "../../../interfaces/IAmmCloseSwapLens.sol"; @@ -14,8 +13,6 @@ import {IAmmCloseSwapLens} from "../../../interfaces/IAmmCloseSwapLens.sol"; /// @dev Close Swap Service for wstEth pool - Asset Management (PlasmaVault from Ipor Fusion) and rebalancing between AMM Treasury /// and Asset Management (PlasmaVault from Ipor Fusion) IS supported in this contract. contract AmmCloseSwapServiceWstEthBaseV2 is AmmCloseSwapServiceBaseV2, IAmmCloseSwapServiceWstEth { - using IporContractValidator for address; - constructor( IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg, address iporOracle_ diff --git a/contracts/base/amm-wstEth/services/AmmOpenSwapServiceWstEthBaseV1.sol b/contracts/base/amm-wstEth/services/AmmOpenSwapServiceWstEthBaseV1.sol index 58ed5cdae..23c225603 100644 --- a/contracts/base/amm-wstEth/services/AmmOpenSwapServiceWstEthBaseV1.sol +++ b/contracts/base/amm-wstEth/services/AmmOpenSwapServiceWstEthBaseV1.sol @@ -11,7 +11,6 @@ import {StorageLibBaseV1} from "../../libraries/StorageLibBaseV1.sol"; /// @dev Open Swap Service for wstETH pool. contract AmmOpenSwapServiceWstEthBaseV1 is AmmOpenSwapServiceBaseV1, IAmmOpenSwapServiceWstEth { using SafeERC20Upgradeable for IERC20Upgradeable; - using IporContractValidator for address; modifier onlySupportedInputAsset(address inputAsset) { if (inputAsset == asset) { diff --git a/contracts/base/amm/AmmStorageBaseV1.sol b/contracts/base/amm/AmmStorageBaseV1.sol index e88163b21..24e1a98be 100644 --- a/contracts/base/amm/AmmStorageBaseV1.sol +++ b/contracts/base/amm/AmmStorageBaseV1.sol @@ -27,7 +27,6 @@ contract AmmStorageBaseV1 is { using IporContractValidator for address; using SafeCast for uint256; - using SafeCast for int256; using SoapIndicatorRebalanceLogic for AmmStorageTypes.SoapIndicators; /// @dev to achieve 18 decimals precision we multiply by 1e12 because for stETH pool liquidationDepositAmount is represented in 6 decimals in storage. diff --git a/contracts/base/amm/libraries/SwapLogicBaseV1.sol b/contracts/base/amm/libraries/SwapLogicBaseV1.sol index 96243a817..47b3a3e09 100644 --- a/contracts/base/amm/libraries/SwapLogicBaseV1.sol +++ b/contracts/base/amm/libraries/SwapLogicBaseV1.sol @@ -13,7 +13,6 @@ import "../../types/AmmTypesBaseV1.sol"; library SwapLogicBaseV1 { using SafeCast for uint256; using InterestRates for uint256; - using InterestRates for int256; /// @notice Calculates core amounts related with swap /// @param tenor swap duration, 0 = 28 days, 1 = 60 days, 2 = 90 days diff --git a/contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol b/contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol index 061b3ece9..d2855ddaf 100644 --- a/contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmCloseSwapServiceBaseV1.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "../../../interfaces/types/IporTypes.sol"; @@ -10,26 +9,20 @@ import "../../../interfaces/IIporOracle.sol"; import "../../../interfaces/IAmmCloseSwapService.sol"; import "../../../libraries/math/IporMath.sol"; import "../../../libraries/IporContractValidator.sol"; -import "../../../libraries/AmmLib.sol"; import "../../interfaces/IAmmStorageBaseV1.sol"; import "../../types/AmmTypesBaseV1.sol"; import "../../events/AmmEventsBaseV1.sol"; import "../../../amm/libraries/types/AmmInternalTypes.sol"; import "../../../base/spread/SpreadBaseV1.sol"; -import "../libraries/SwapLogicBaseV1.sol"; import "../libraries/SwapCloseLogicLibBaseV1.sol"; import "../../interfaces/ISpreadBaseV1.sol"; /// @title Abstract contract for closing swap, generation one, characterized by: /// - no asset management, so also no auto rebalance abstract contract AmmCloseSwapServiceBaseV1 is IAmmCloseSwapService { - using Address for address; using IporContractValidator for address; using SafeCast for uint256; - using SafeCast for int256; using SafeERC20Upgradeable for IERC20Upgradeable; - using SwapLogicBaseV1 for AmmTypesBaseV1.Swap; - using AmmLib for AmmTypes.AmmPoolCoreModel; address public immutable asset; uint256 public immutable decimals; diff --git a/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol b/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol index 4eba63cd6..167d5551a 100644 --- a/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol +++ b/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol @@ -7,16 +7,13 @@ import {SafeERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ER import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol"; import {IAmmTreasuryBaseV2} from "../../interfaces/IAmmTreasuryBaseV2.sol"; import {AmmCloseSwapServiceBaseV1} from "./AmmCloseSwapServiceBaseV1.sol"; -import "../../../interfaces/types/IporTypes.sol"; import "../../../interfaces/types/AmmTypes.sol"; -import "../../../interfaces/IIporOracle.sol"; import "../../../interfaces/IAmmCloseSwapService.sol"; import "../../../libraries/math/IporMath.sol"; import "../../../libraries/IporContractValidator.sol"; import "../../../libraries/AmmLib.sol"; import "../../interfaces/IAmmStorageBaseV1.sol"; import "../../types/AmmTypesBaseV1.sol"; -import "../../events/AmmEventsBaseV1.sol"; import "../../../amm/libraries/types/AmmInternalTypes.sol"; import "../../../base/spread/SpreadBaseV1.sol"; import "../libraries/SwapLogicBaseV1.sol"; diff --git a/contracts/base/amm/services/AmmOpenSwapServiceBaseV1.sol b/contracts/base/amm/services/AmmOpenSwapServiceBaseV1.sol index 74f7ded78..12217a946 100644 --- a/contracts/base/amm/services/AmmOpenSwapServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmOpenSwapServiceBaseV1.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; import "../../../interfaces/IIporOracle.sol"; import "../../interfaces/IAmmTreasuryBaseV1.sol"; @@ -16,7 +15,6 @@ import "../../../base/interfaces/IAmmStorageBaseV1.sol"; /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. abstract contract AmmOpenSwapServiceBaseV1 { - using Address for address; using IporContractValidator for address; using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; diff --git a/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol b/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol index 24454c320..4ce57b9f8 100644 --- a/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol @@ -7,13 +7,9 @@ import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20 import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol"; import {IProvideLiquidityEvents} from "../../../interfaces/IProvideLiquidityEvents.sol"; import {IAmmTreasuryBaseV2} from "../../../base/interfaces/IAmmTreasuryBaseV2.sol"; -import "../../../interfaces/types/IporTypes.sol"; import "../../../interfaces/types/AmmTypes.sol"; import "../../../interfaces/IIpToken.sol"; -import "../../../interfaces/IAmmTreasury.sol"; -import "../../../interfaces/IAmmPoolsService.sol"; import "../../../interfaces/IAmmStorage.sol"; -import "../../../libraries/Constants.sol"; import "../../../libraries/errors/IporErrors.sol"; import "../../../libraries/errors/AmmErrors.sol"; import "../../../libraries/errors/AmmPoolsErrors.sol"; diff --git a/contracts/base/amm/services/AmmSwapsLensBaseV1.sol b/contracts/base/amm/services/AmmSwapsLensBaseV1.sol index 86271c319..879dbe92d 100644 --- a/contracts/base/amm/services/AmmSwapsLensBaseV1.sol +++ b/contracts/base/amm/services/AmmSwapsLensBaseV1.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; import "../../../interfaces/IAmmSwapsLens.sol"; import "../../../base/amm/libraries/AmmSwapsLensLibBaseV1.sol"; import "../../../libraries/IporContractValidator.sol"; @@ -11,7 +10,6 @@ import {StorageLibBaseV1} from "../../libraries/StorageLibBaseV1.sol"; /// @dev It is not recommended to use lens contract directly, should be used only through IporProtocolRouter. contract AmmSwapsLensBaseV1 is IAmmSwapsLens { - using Address for address; using IporContractValidator for address; using AmmLib for AmmTypes.AmmPoolCoreModel; using RiskIndicatorsValidatorLib for AmmTypes.RiskIndicatorsInputs; diff --git a/contracts/base/spread/SpreadBaseV1.sol b/contracts/base/spread/SpreadBaseV1.sol index 513047687..5df5fef84 100644 --- a/contracts/base/spread/SpreadBaseV1.sol +++ b/contracts/base/spread/SpreadBaseV1.sol @@ -19,7 +19,6 @@ import "./OfferedRateCalculationLibsBaseV1.sol"; contract SpreadBaseV1 is IporOwnable, ISpreadBaseV1 { error UnknownTenor(IporTypes.SwapTenor tenor, string errorCode, string methodName); using IporContractValidator for address; - using SafeCast for uint256; using SafeCast for int256; address public immutable asset; diff --git a/contracts/base/spread/SpreadBaseV2.sol b/contracts/base/spread/SpreadBaseV2.sol index c86a861c9..ffa025ec8 100644 --- a/contracts/base/spread/SpreadBaseV2.sol +++ b/contracts/base/spread/SpreadBaseV2.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {IporTypes} from "../../interfaces/types/IporTypes.sol"; import {AmmTypes} from "../../interfaces/types/AmmTypes.sol"; import {IporContractValidator} from "../../libraries/IporContractValidator.sol"; @@ -25,7 +24,6 @@ import {AmmErrors} from "../../libraries/errors/AmmErrors.sol"; abstract contract SpreadBaseV2 is IporOwnable, ISpreadBaseV1 { error UnknownTenor(IporTypes.SwapTenor tenor, string errorCode, string methodName); using IporContractValidator for address; - using SafeCast for uint256; address public immutable asset; address public immutable iporProtocolRouter; diff --git a/contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol b/contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol index f6247796a..7dbd562d5 100644 --- a/contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol +++ b/contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol @@ -1,19 +1,9 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.26; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import "../../../interfaces/IIpToken.sol"; -import "../../../interfaces/types/AmmTypes.sol"; -import "../../../libraries/errors/AmmErrors.sol"; -import "../../../libraries/math/IporMath.sol"; -import "../../../libraries/StorageLib.sol"; -import "../../../libraries/IporContractValidator.sol"; import "../../../libraries/AmmLib.sol"; -import "../../../governance/AmmConfigurationManager.sol"; -import "../../../base/interfaces/IAmmTreasuryBaseV1.sol"; import {IAmmPoolsServiceUsdc} from "../interfaces/IAmmPoolsServiceUsdc.sol"; import {AmmPoolsServiceBaseV1} from "../../../base/amm/services/AmmPoolsServiceBaseV1.sol"; diff --git a/contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol b/contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol index 79325b6ac..715f05131 100644 --- a/contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol +++ b/contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol @@ -8,7 +8,6 @@ import {StorageLibArbitrum} from "../libraries/StorageLibArbitrum.sol"; /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. /// @dev Service can be safely used directly only if you are sure that methods will not touch any storage variables. contract AmmCloseSwapServiceWstEth is AmmCloseSwapServiceBaseV1, IAmmCloseSwapServiceWstEth { - using IporContractValidator for address; constructor( IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg, diff --git a/contracts/chains/base/router/IporProtocolRouterBase.sol b/contracts/chains/base/router/IporProtocolRouterBase.sol index 3c5c0954c..2241182b0 100644 --- a/contracts/chains/base/router/IporProtocolRouterBase.sol +++ b/contracts/chains/base/router/IporProtocolRouterBase.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {IPowerTokenLens} from "../../../interfaces/IPowerTokenLens.sol"; import {IPowerTokenFlowsService} from "../../../interfaces/IPowerTokenFlowsService.sol"; import {ILiquidityMiningLens} from "../../../interfaces/ILiquidityMiningLens.sol"; @@ -28,7 +27,6 @@ import {IporProtocolRouterAbstract} from "../../../router/IporProtocolRouterAbst /// @title Entry point for IPOR protocol contract IporProtocolRouterBase is IporProtocolRouterAbstract { - using Address for address; using IporContractValidator for address; address public immutable ammSwapsLens; diff --git a/contracts/chains/ethereum/router/IporProtocolRouter.sol b/contracts/chains/ethereum/router/IporProtocolRouter.sol index dcf0fa401..9ab9dc67a 100644 --- a/contracts/chains/ethereum/router/IporProtocolRouter.sol +++ b/contracts/chains/ethereum/router/IporProtocolRouter.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import "@openzeppelin/contracts/utils/Address.sol"; - import "../../../interfaces/IAmmSwapsLens.sol"; import "../../../interfaces/IAmmPoolsLens.sol"; import "../../../interfaces/IAssetManagementLens.sol"; @@ -33,7 +31,6 @@ import "../../../amm-usdm/interfaces/IAmmPoolsLensUsdm.sol"; /// @title Entry point for IPOR protocol contract IporProtocolRouter is IporProtocolRouterAbstract { - using Address for address; using IporContractValidator for address; address public immutable ammSwapsLens; diff --git a/contracts/interfaces/IAssetManagement.sol b/contracts/interfaces/IAssetManagement.sol index f2c3cc423..3079c408f 100644 --- a/contracts/interfaces/IAssetManagement.sol +++ b/contracts/interfaces/IAssetManagement.sol @@ -37,8 +37,4 @@ interface IAssetManagement { /// @param amount of asset transferred from AmmTreasury to AssetManagement, represented in 18 decimals event Deposit(address from, address to, uint256 amount); - /// @notice Emitted when AmmTreasury executes withdraw function. - /// @param to account address where assets are transferred to - /// @param amount of asset transferred from AmmTreasury to AssetManagement, represented in 18 decimals - event Withdraw(address to, uint256 amount); } diff --git a/contracts/libraries/AmmLib.sol b/contracts/libraries/AmmLib.sol index 728f6118f..ee7939dc1 100644 --- a/contracts/libraries/AmmLib.sol +++ b/contracts/libraries/AmmLib.sol @@ -7,7 +7,6 @@ import "../interfaces/types/AmmStorageTypes.sol"; import "../interfaces/IIpToken.sol"; import "../interfaces/IIporOracle.sol"; import "../interfaces/IAmmStorage.sol"; -import "../interfaces/IAssetManagement.sol"; import "./errors/IporErrors.sol"; import "./errors/AmmErrors.sol"; import "./math/IporMath.sol"; diff --git a/contracts/libraries/errors/IporErrors.sol b/contracts/libraries/errors/IporErrors.sol index bac9ac4dd..40ba4fa67 100644 --- a/contracts/libraries/errors/IporErrors.sol +++ b/contracts/libraries/errors/IporErrors.sol @@ -14,9 +14,6 @@ library IporErrors { /// @notice Error when caller is not a pause guardian error CallerNotPauseGuardian(string errorCode, address caller); - /// @notice Error when caller is not a AmmTreasury contract - error CallerNotAmmTreasury(string errorCode, address caller); - /// @notice Error when given direction is not supported error UnsupportedDirection(string errorCode, uint256 direction); From b7ce8efd6f68652286ce3c8b715422df63460349 Mon Sep 17 00:00:00 2001 From: Mario <85162486+mario-ipor@users.noreply.github.com> Date: Tue, 4 Nov 2025 07:32:13 +0100 Subject: [PATCH 5/6] IL-5751 IPOR Fusion prep. integration for: Ethereum: stETH, weETH pools, Arbitrum: wstETH pool (#759) --- contracts/amm-eth/AmmPoolsLensStEth.sol | 48 -- contracts/amm-eth/AmmPoolsServiceStEth.sol | 193 ------ .../amm-eth/interfaces/IAmmPoolsLensStEth.sol | 10 - .../interfaces/IAmmPoolsServiceStEth.sol | 6 + contracts/amm-usdm/AmmPoolsLensUsdm.sol | 48 -- contracts/amm-usdm/AmmPoolsServiceUsdm.sol | 3 +- .../amm-usdm/interfaces/IAmmPoolsLensUsdm.sol | 10 - .../interfaces/IAmmPoolsServiceUsdm.sol | 2 +- contracts/amm-weEth/AmmPoolsLensWeEth.sol | 48 -- .../interfaces/IAmmPoolsLensWeEth.sol | 10 - .../interfaces/IAmmPoolsServiceWeEth.sol | 4 +- .../interfaces/IEEthLiquidityPool.sol | 1 + contracts/amm/AmmCloseSwapServiceStable.sol | 2 +- contracts/amm/AmmPoolsService.sol | 8 +- .../AmmCloseSwapServiceStEthBaseV2.sol} | 27 +- .../IAmmPoolsServiceWeEthBaseV1.sol | 19 + .../services/AmmPoolsServiceWeEthBaseV1.sol | 55 ++ .../IAmmPoolsServiceWstEthBaseV1.sol | 2 +- .../IAmmPoolsServiceWstEthBaseV2.sol | 2 +- .../services/AmmPoolsServiceWstEthBaseV1.sol | 3 +- .../services/AmmPoolsServiceWstEthBaseV2.sol | 2 +- contracts/base/amm/AmmTreasuryBaseV2.sol | 14 +- .../services/AmmCloseSwapServiceBaseV2.sol | 2 +- .../services/AmmGovernanceServiceBaseV1.sol | 2 +- .../amm/services/AmmPoolsServiceBaseV1.sol | 77 ++- .../AmmGovernanceServiceArbitrum.sol | 2 +- .../arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol | 43 -- .../amm-wstEth/AmmCloseSwapServiceWstEth.sol | 60 -- .../amm-wstEth/AmmOpenSwapServiceWstEth.sol | 190 ------ .../amm-wstEth/AmmPoolsServiceWstEth.sol | 140 ++--- .../router/IporProtocolRouterArbitrum.sol | 14 +- .../ethereum/amm-commons/AmmCloseSwapLens.sol | 186 +----- .../amm-commons/AmmGovernanceService.sol | 362 ----------- .../amm-stEth}/AmmOpenSwapServiceStEth.sol | 28 +- .../amm-stEth/AmmPoolsServiceStEth.sol | 199 ++++++ .../amm-weEth/AmmPoolsServiceWeEth.sol | 174 +++--- ...ter.sol => IporProtocolRouterEthereum.sol} | 190 +++--- .../governance/AmmConfigurationManager.sol | 22 +- contracts/interfaces/IIporProtocol.sol | 6 - contracts/libraries/StorageLib.sol | 147 ----- contracts/router/AccessControl.sol | 23 +- .../router/IporProtocolRouterAbstract.sol | 6 +- contracts/security/OwnerManager.sol | 12 +- contracts/security/PauseManager.sol | 8 +- test/AmmStorageLastOpenSwap.t.sol | 2 +- test/IporLogic.t.sol | 2 +- test/IporProtocolRouter.t.sol | 260 ++------ .../IporSwapLogicCalculateSwapAmount.t.sol | 2 +- .../SwapLogicCalculateInterest.t.sol | 2 +- .../SwapLogicCalculateInterestFixed.t.sol | 2 +- .../SwapLogicCalculateInterestFloating.t.sol | 2 +- .../SwapLogicCalculateSwapPayFixedValue.t.sol | 2 +- ...pLogicCalculateSwapReceiveFixedValue.t.sol | 2 +- test/SoapIndicatorLogic.t.sol | 82 ++- test/amm-eth/EthRebalance.t.sol | 120 ++++ test/amm-eth/ProvideBatchExecutor.t.sol | 29 +- test/amm-eth/ProvideEth.t.sol | 27 +- test/amm-eth/ProvideStEth.t.sol | 29 +- test/amm-eth/ProvideWEth.t.sol | 39 +- test/amm-eth/RedeemStEth.t.sol | 9 +- test/amm-eth/TestEthMarketCommons.sol | 201 +++--- .../ethereum/ProvideUsdmEthereum.t.sol | 18 +- .../UsdmForkAmmUsdmExchangeRateEthereum.t.sol | 22 +- .../ethereum/UsdmTestForkCommonEthereum.sol | 194 +++--- test/amm-weEth/ProvideWeEth.t.sol | 109 ++-- .../WeEthForkAmmGovernanceServiceTest.t.sol | 15 +- .../WeEthForkAmmWeEthExchangeRate.t.sol | 29 +- test/amm-weEth/WeEthRebalance.t.sol | 131 ++++ test/amm-weEth/WeEthTestForkCommon.sol | 127 +++- test/amm/AmmClosingSwaps.t.sol | 2 +- test/amm/AmmEvents.t.sol | 2 +- test/amm/AmmGovernanceService.t.sol | 2 +- test/amm/AmmPoolsExchangeRateAndSoap.t.sol | 2 +- test/amm/AmmPoolsExchangeRateLiquidity.t.sol | 2 +- test/amm/AmmPoolsNotChangeExchangeRate.t.sol | 4 +- test/amm/AmmPoolsServiceNotRedeem.t.sol | 2 +- test/amm/AmmPoolsServiceOnlyRebalance.t.sol | 2 +- .../amm/AmmPoolsServiceProvideLiquidity.t.sol | 2 +- ...sServiceProvideLiquidityAndRebalance.t.sol | 2 +- test/amm/AmmPoolsServiceRedeem.t.sol | 2 +- test/amm/AmmShouldClosePosition.t.sol | 2 +- test/amm/AmmSoap.t.sol | 2 +- test/amm/AmmSoapAndCloseSwap.t.sol | 2 +- test/amm/AmmStorage.t.sol | 2 +- test/amm/AmmSwapLensOfferedRate.t.sol | 2 +- test/amm/AmmTreasury.t.sol | 2 +- test/amm/AmmUnwindSwap.t.sol | 2 +- test/arbitrum/ArbitrumTestForkCommons.sol | 343 +++++----- .../usdc/ArbitrumForkAmmUsdcRebalance.t.sol | 123 ++++ .../usdc/UsdcTestForkCommonArbitrum.sol | 12 +- .../ArbitrumForkAmmWstEthRebalance.t.sol | 115 ++++ .../ArbitrumForkAmmWstEthSwapsUnwind.t.sol | 6 +- .../IporSwapLogicCalculateSwapAmount.t.sol | 2 +- .../SwapLogicCalculateInterest.t.sol | 2 +- .../SwapLogicCalculateSwapPayFixedValue.t.sol | 2 +- ...pLogicCalculateSwapReceiveFixedValue.t.sol | 2 +- .../BaseForkAmmWstEthCloseSwaps.t.sol | 2 + test/chain-base/BaseTestForkCommons.sol | 34 +- test/fork/ForkAmmStEthExchangeRate.t.sol | 173 +++-- test/fork/ForkAmmStEthOpenSwaps.t.sol | 15 +- test/fork/ForkIporProtocolRouterCases.t.sol | 8 +- test/fork/TestForkCommons.sol | 437 +++++++++---- test/iporOracle/IporOracle.t.sol | 2 +- test/iporOracle/IporOracleStEth.t.sol | 44 +- test/libraries/math/IporMath.t.sol | 36 +- test/mocks/Multicall2.sol | 2 +- test/mocks/Multicall3.sol | 70 ++- test/security/IporOwnable.t.sol | 2 +- test/security/IporOwnableUpgradeable.t.sol | 2 +- .../CalculateWeightedNotionalLibsTest.t.sol | 2 +- test/spread/SpreadAccessControl.t.sol | 2 +- test/spread/SpreadBaseTestUtils.sol | 2 +- test/spread/SpreadRouter.t.sol | 2 +- test/spread/SpreadSmoke.t.sol | 2 +- test/spread/SpreadStorageTest.t.sol | 2 +- test/spread/SpreadTestSystem.sol | 2 +- ...culateWeightedNotionalLibsBaseV1Test.t.sol | 2 +- test/tokens/IpToken.t.sol | 2 +- test/tokens/IporToken.t.sol | 2 +- test/utils/builder/BuilderUtils.sol | 4 +- .../builder/IporProtocolRouterBuilder.sol | 137 ++-- test/utils/factory/IporProtocolFactory.sol | 589 ++++++++++-------- 122 files changed, 2894 insertions(+), 3195 deletions(-) delete mode 100644 contracts/amm-eth/AmmPoolsLensStEth.sol delete mode 100644 contracts/amm-eth/AmmPoolsServiceStEth.sol delete mode 100644 contracts/amm-eth/interfaces/IAmmPoolsLensStEth.sol delete mode 100644 contracts/amm-usdm/AmmPoolsLensUsdm.sol delete mode 100644 contracts/amm-usdm/interfaces/IAmmPoolsLensUsdm.sol delete mode 100644 contracts/amm-weEth/AmmPoolsLensWeEth.sol delete mode 100644 contracts/amm-weEth/interfaces/IAmmPoolsLensWeEth.sol rename contracts/{amm-eth/AmmCloseSwapServiceStEth.sol => base/amm-stEth/services/AmmCloseSwapServiceStEthBaseV2.sol} (70%) create mode 100644 contracts/base/amm-weEth/interfaces/IAmmPoolsServiceWeEthBaseV1.sol create mode 100644 contracts/base/amm-weEth/services/AmmPoolsServiceWeEthBaseV1.sol delete mode 100644 contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol delete mode 100644 contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol delete mode 100644 contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol delete mode 100644 contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol rename contracts/{amm-eth => chains/ethereum/amm-stEth}/AmmOpenSwapServiceStEth.sol (90%) create mode 100644 contracts/chains/ethereum/amm-stEth/AmmPoolsServiceStEth.sol rename contracts/{ => chains/ethereum}/amm-weEth/AmmPoolsServiceWeEth.sol (53%) rename contracts/chains/ethereum/router/{IporProtocolRouter.sol => IporProtocolRouterEthereum.sol} (82%) delete mode 100644 contracts/libraries/StorageLib.sol create mode 100644 test/amm-eth/EthRebalance.t.sol create mode 100644 test/amm-weEth/WeEthRebalance.t.sol create mode 100644 test/arbitrum/usdc/ArbitrumForkAmmUsdcRebalance.t.sol create mode 100644 test/arbitrum/wstETH/ArbitrumForkAmmWstEthRebalance.t.sol diff --git a/contracts/amm-eth/AmmPoolsLensStEth.sol b/contracts/amm-eth/AmmPoolsLensStEth.sol deleted file mode 100644 index 132d33900..000000000 --- a/contracts/amm-eth/AmmPoolsLensStEth.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.26; - -import "./interfaces/IAmmPoolsLensStEth.sol"; -import "../interfaces/types/AmmTypes.sol"; -import "../base/interfaces/IAmmTreasuryBaseV1.sol"; -import "../libraries/IporContractValidator.sol"; -import "../libraries/AmmLib.sol"; - -/// @dev It is not recommended to use lens contract directly, should be used only through IporProtocolRouter. -contract AmmPoolsLensStEth is IAmmPoolsLensStEth { - using IporContractValidator for address; - using AmmLib for AmmTypes.AmmPoolCoreModel; - - address public immutable stEth; - address public immutable ipstEth; - address public immutable ammTreasuryStEth; - address public immutable ammStorageStEth; - address public immutable iporOracle; - - constructor( - address stEthInput, - address ipstEthInput, - address ammTreasuryStEthInput, - address ammStorageStEthInput, - address iporOracleInput - ) { - stEth = stEthInput.checkAddress(); - ipstEth = ipstEthInput.checkAddress(); - ammTreasuryStEth = ammTreasuryStEthInput.checkAddress(); - ammStorageStEth = ammStorageStEthInput.checkAddress(); - iporOracle = iporOracleInput.checkAddress(); - } - - function getIpstEthExchangeRate() external view returns (uint256) { - AmmTypes.AmmPoolCoreModel memory model = AmmTypes.AmmPoolCoreModel({ - asset: stEth, - assetDecimals: 18, - ipToken: ipstEth, - ammStorage: ammStorageStEth, - ammTreasury: ammTreasuryStEth, - assetManagement: address(0), - iporOracle: iporOracle - }); - uint256 liquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryStEth).getLiquidityPoolBalance(); - return model.getExchangeRate(liquidityPoolBalance); - } -} diff --git a/contracts/amm-eth/AmmPoolsServiceStEth.sol b/contracts/amm-eth/AmmPoolsServiceStEth.sol deleted file mode 100644 index fdf28a542..000000000 --- a/contracts/amm-eth/AmmPoolsServiceStEth.sol +++ /dev/null @@ -1,193 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "../interfaces/IIpToken.sol"; -import "../interfaces/types/AmmTypes.sol"; -import "./interfaces/IStETH.sol"; -import "./interfaces/IWETH9.sol"; -import "./interfaces/IAmmPoolsServiceStEth.sol"; -import "../libraries/errors/AmmErrors.sol"; -import "../libraries/math/IporMath.sol"; -import "../libraries/StorageLib.sol"; -import "../libraries/IporContractValidator.sol"; -import "../libraries/AmmLib.sol"; -import "../governance/AmmConfigurationManager.sol"; -import "../base/interfaces/IAmmTreasuryBaseV1.sol"; - -/// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. -contract AmmPoolsServiceStEth is IAmmPoolsServiceStEth { - using IporContractValidator for address; - using SafeERC20 for IStETH; - using SafeERC20 for IWETH9; - using AmmLib for AmmTypes.AmmPoolCoreModel; - - address public immutable stEth; - address public immutable wEth; - address public immutable ipstEth; - address public immutable ammTreasuryStEth; - address public immutable ammStorageStEth; - address public immutable iporOracle; - address public immutable iporProtocolRouter; - uint256 public immutable redeemFeeRateStEth; - - constructor( - address stEthInput, - address wEthInput, - address ipstEthInput, - address ammTreasuryStEthInput, - address ammStorageStEthInput, - address iporOracleInput, - address iporProtocolRouterInput, - uint256 redeemFeeRateStEthInput - ) { - stEth = stEthInput.checkAddress(); - wEth = wEthInput.checkAddress(); - ipstEth = ipstEthInput.checkAddress(); - ammTreasuryStEth = ammTreasuryStEthInput.checkAddress(); - ammStorageStEth = ammStorageStEthInput.checkAddress(); - iporOracle = iporOracleInput.checkAddress(); - iporProtocolRouter = iporProtocolRouterInput.checkAddress(); - redeemFeeRateStEth = redeemFeeRateStEthInput; - - require(redeemFeeRateStEthInput <= 1e18, AmmPoolsErrors.CFG_INVALID_REDEEM_FEE_RATE); - } - - function provideLiquidityStEth(address beneficiary, uint256 stEthAmount) external payable override { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(stEth); - - uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryStEth).getLiquidityPoolBalance(); - uint256 newPoolBalance = actualLiquidityPoolBalance + stEthAmount; - - require( - newPoolBalance <= uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, - AmmErrors.LIQUIDITY_POOL_BALANCE_IS_TOO_HIGH - ); - - uint256 exchangeRate = _getExchangeRate(actualLiquidityPoolBalance); - - IStETH(stEth).safeTransferFrom(msg.sender, ammTreasuryStEth, stEthAmount); - - uint256 ipTokenAmount = IporMath.division(stEthAmount * 1e18, exchangeRate); - - IIpToken(ipstEth).mint(beneficiary, ipTokenAmount); - - emit IAmmPoolsServiceStEth.ProvideLiquidityStEth( - msg.sender, - beneficiary, - ammTreasuryStEth, - exchangeRate, - stEthAmount, - ipTokenAmount - ); - } - - function provideLiquidityWEth(address beneficiary, uint256 wEthAmount) external payable override { - require(wEthAmount > 0, IporErrors.VALUE_NOT_GREATER_THAN_ZERO); - - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(stEth); - uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryStEth).getLiquidityPoolBalance(); - uint256 newPoolBalance = wEthAmount + actualLiquidityPoolBalance; - - require( - newPoolBalance <= uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, - AmmErrors.LIQUIDITY_POOL_BALANCE_IS_TOO_HIGH - ); - - IWETH9(wEth).safeTransferFrom(msg.sender, iporProtocolRouter, wEthAmount); - IWETH9(wEth).withdraw(wEthAmount); - - _depositEth(wEthAmount, beneficiary, actualLiquidityPoolBalance); - } - - function provideLiquidityEth(address beneficiary, uint256 ethAmount) external payable { - require(ethAmount > 0, IporErrors.VALUE_NOT_GREATER_THAN_ZERO); - require(msg.value > 0, IporErrors.VALUE_NOT_GREATER_THAN_ZERO); - - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(stEth); - uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryStEth).getLiquidityPoolBalance(); - uint256 newPoolBalance = ethAmount + actualLiquidityPoolBalance; - - require( - newPoolBalance <= uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, - AmmErrors.LIQUIDITY_POOL_BALANCE_IS_TOO_HIGH - ); - - _depositEth(ethAmount, beneficiary, actualLiquidityPoolBalance); - } - - function redeemFromAmmPoolStEth(address beneficiary, uint256 ipTokenAmount) external { - require( - ipTokenAmount > 0 && ipTokenAmount <= IIpToken(ipstEth).balanceOf(msg.sender), - AmmPoolsErrors.CANNOT_REDEEM_IP_TOKEN_TOO_LOW - ); - require(beneficiary != address(0), IporErrors.WRONG_ADDRESS); - - uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryStEth).getLiquidityPoolBalance(); - - uint256 exchangeRate = _getExchangeRate(actualLiquidityPoolBalance); - - uint256 stEthAmount = IporMath.division(ipTokenAmount * exchangeRate, 1e18); - - uint256 amountToRedeem = IporMath.division(stEthAmount * (1e18 - redeemFeeRateStEth), 1e18); - - require(amountToRedeem > 0, AmmPoolsErrors.CANNOT_REDEEM_ASSET_AMOUNT_TOO_LOW); - - IIpToken(ipstEth).burn(msg.sender, ipTokenAmount); - - IStETH(stEth).safeTransferFrom(ammTreasuryStEth, beneficiary, amountToRedeem); - - emit RedeemStEth( - ammTreasuryStEth, - msg.sender, - beneficiary, - exchangeRate, - stEthAmount, - amountToRedeem, - ipTokenAmount - ); - } - - function _depositEth(uint256 ethAmount, address beneficiary, uint256 actualLiquidityPoolBalance) private { - try IStETH(stEth).submit{value: ethAmount}(address(0)) { - uint256 stEthAmount = IStETH(stEth).balanceOf(address(this)); - - if (stEthAmount > 0) { - uint256 exchangeRate = _getExchangeRate(actualLiquidityPoolBalance); - - IStETH(stEth).safeTransfer(ammTreasuryStEth, stEthAmount); - - uint256 ipTokenAmount = IporMath.division(stEthAmount * 1e18, exchangeRate); - - IIpToken(ipstEth).mint(beneficiary, ipTokenAmount); - - emit IAmmPoolsServiceStEth.ProvideLiquidityEth( - msg.sender, - beneficiary, - ammTreasuryStEth, - exchangeRate, - ethAmount, - stEthAmount, - ipTokenAmount - ); - } - } catch { - revert IAmmPoolsServiceStEth.StEthSubmitFailed({ - amount: ethAmount, - errorCode: AmmErrors.STETH_SUBMIT_FAILED - }); - } - } - - function _getExchangeRate(uint256 actualLiquidityPoolBalance) internal view returns (uint256) { - AmmTypes.AmmPoolCoreModel memory model = AmmTypes.AmmPoolCoreModel({ - asset: stEth, - assetDecimals: 18, - ipToken: ipstEth, - ammStorage: ammStorageStEth, - ammTreasury: ammTreasuryStEth, - assetManagement: address(0), - iporOracle: iporOracle - }); - return model.getExchangeRate(actualLiquidityPoolBalance); - } -} diff --git a/contracts/amm-eth/interfaces/IAmmPoolsLensStEth.sol b/contracts/amm-eth/interfaces/IAmmPoolsLensStEth.sol deleted file mode 100644 index c674c8e6e..000000000 --- a/contracts/amm-eth/interfaces/IAmmPoolsLensStEth.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.26; - -/// @title Interface of the AmmPoolsLensStEth contract. -interface IAmmPoolsLensStEth { - /// @notice Retrieves the exchange rate between stEth and ipstEth using the AmmLibEth library. - /// @return The exchange rate calculated based on the balance of stEth in the AMM Treasury and the total supply of ipstEth. - /// @dev This function acts as a wrapper around the `getExchangeRate` function in the AmmLibEth library. - function getIpstEthExchangeRate() external view returns (uint256); -} diff --git a/contracts/amm-eth/interfaces/IAmmPoolsServiceStEth.sol b/contracts/amm-eth/interfaces/IAmmPoolsServiceStEth.sol index 939934341..084d88dfc 100644 --- a/contracts/amm-eth/interfaces/IAmmPoolsServiceStEth.sol +++ b/contracts/amm-eth/interfaces/IAmmPoolsServiceStEth.sol @@ -50,6 +50,12 @@ interface IAmmPoolsServiceStEth { /// require The calculated stEth amount to redeem after accounting for the fee should be greater than zero. function redeemFromAmmPoolStEth(address beneficiary, uint256 ipTokenAmount) external; + /// @notice Rebalances stETH assets between the AmmTreasury and the AssetManagement, based on configuration stored + /// in the `AmmPoolsParamsValue.ammTreasuryAndAssetManagementRatio` field. + /// @dev Emits {Deposit} or {Withdraw} event from AssetManagement depends on current asset balance on AmmTreasury and AssetManagement. + /// @dev Emits {Transfer} from ERC20 asset. + function rebalanceBetweenAmmTreasuryAndAssetManagementStEth() external; + /// @notice Error appeared when submitted ETH amount to in stETH contract is too high. /// @param amount Amount of ETH which was submitted to stETH contract. /// @param errorCode IPOR Protocol error code. diff --git a/contracts/amm-usdm/AmmPoolsLensUsdm.sol b/contracts/amm-usdm/AmmPoolsLensUsdm.sol deleted file mode 100644 index cfecdeee3..000000000 --- a/contracts/amm-usdm/AmmPoolsLensUsdm.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.26; - -import "./interfaces/IAmmPoolsLensUsdm.sol"; -import "../interfaces/types/AmmTypes.sol"; -import "../base/interfaces/IAmmTreasuryBaseV1.sol"; -import "../libraries/IporContractValidator.sol"; -import "../libraries/AmmLib.sol"; - -/// @dev It is not recommended to use lens contract directly, should be used only through IporProtocolRouter. -contract AmmPoolsLensUsdm is IAmmPoolsLensUsdm { - using IporContractValidator for address; - using AmmLib for AmmTypes.AmmPoolCoreModel; - - address public immutable usdm; - address public immutable ipUsdm; - address public immutable ammTreasuryUsdm; - address public immutable ammStorageUsdm; - address public immutable iporOracle; - - constructor( - address usdmInput, - address ipUsdmInput, - address ammTreasuryUsdmInput, - address ammStorageUsdmInput, - address iporOracleInput - ) { - usdm = usdmInput.checkAddress(); - ipUsdm = ipUsdmInput.checkAddress(); - ammTreasuryUsdm = ammTreasuryUsdmInput.checkAddress(); - ammStorageUsdm = ammStorageUsdmInput.checkAddress(); - iporOracle = iporOracleInput.checkAddress(); - } - - function getIpUsdmExchangeRate() external view returns (uint256) { - AmmTypes.AmmPoolCoreModel memory model = AmmTypes.AmmPoolCoreModel({ - asset: usdm, - assetDecimals: 18, - ipToken: ipUsdm, - ammStorage: ammStorageUsdm, - ammTreasury: ammTreasuryUsdm, - assetManagement: address(0), - iporOracle: iporOracle - }); - uint256 liquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryUsdm).getLiquidityPoolBalance(); - return model.getExchangeRate(liquidityPoolBalance); - } -} diff --git a/contracts/amm-usdm/AmmPoolsServiceUsdm.sol b/contracts/amm-usdm/AmmPoolsServiceUsdm.sol index bf095a428..c62c8d4c3 100644 --- a/contracts/amm-usdm/AmmPoolsServiceUsdm.sol +++ b/contracts/amm-usdm/AmmPoolsServiceUsdm.sol @@ -8,7 +8,6 @@ import "../interfaces/types/AmmTypes.sol"; import "./interfaces/IAmmPoolsServiceUsdm.sol"; import "../libraries/errors/AmmErrors.sol"; import "../libraries/math/IporMath.sol"; -import "../libraries/StorageLib.sol"; import "../libraries/IporContractValidator.sol"; import "../libraries/ProvideLiquidityEvents.sol"; import "../libraries/AmmLib.sol"; @@ -50,7 +49,7 @@ contract AmmPoolsServiceUsdm is IAmmPoolsServiceUsdm { } function provideLiquidityUsdmToAmmPoolUsdm(address beneficiary, uint256 usdmAmount) external payable override { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(usdm); + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(usdm); uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryUsdm).getLiquidityPoolBalance(); uint256 newPoolBalance = actualLiquidityPoolBalance + usdmAmount; diff --git a/contracts/amm-usdm/interfaces/IAmmPoolsLensUsdm.sol b/contracts/amm-usdm/interfaces/IAmmPoolsLensUsdm.sol deleted file mode 100644 index ff8888b51..000000000 --- a/contracts/amm-usdm/interfaces/IAmmPoolsLensUsdm.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.26; - -/// @title Interface of the IAmmPoolsLensUsdm contract. -interface IAmmPoolsLensUsdm { - /// @notice Retrieves the exchange rate between usdm and ipUsdm using the AmmLibEth library. - /// @return The exchange rate calculated based on the balance of usdm in the AMM Treasury and the total supply of ipUsdm. - /// @dev This function acts as a wrapper around the `getExchangeRate` function in the AmmLibEth library. - function getIpUsdmExchangeRate() external view returns (uint256); -} diff --git a/contracts/amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol b/contracts/amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol index 1d2ab8bcc..5f6bf1725 100644 --- a/contracts/amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol +++ b/contracts/amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -/// @title Interface of the AmmPoolsServiceWstEth contract. +/// @title Interface of the AmmPoolsServiceUsdm contract. interface IAmmPoolsServiceUsdm { function provideLiquidityUsdmToAmmPoolUsdm(address beneficiary, uint256 usdmAmount) external payable; diff --git a/contracts/amm-weEth/AmmPoolsLensWeEth.sol b/contracts/amm-weEth/AmmPoolsLensWeEth.sol deleted file mode 100644 index 94f4ea309..000000000 --- a/contracts/amm-weEth/AmmPoolsLensWeEth.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.26; - -import "./interfaces/IAmmPoolsLensWeEth.sol"; -import "../interfaces/types/AmmTypes.sol"; -import "../base/interfaces/IAmmTreasuryBaseV1.sol"; -import "../libraries/IporContractValidator.sol"; -import "../libraries/AmmLib.sol"; - -/// @dev It is not recommended to use lens contract directly, should be used only through IporProtocolRouter. -contract AmmPoolsLensWeEth is IAmmPoolsLensWeEth { - using IporContractValidator for address; - using AmmLib for AmmTypes.AmmPoolCoreModel; - - address public immutable weEth; - address public immutable ipWeEth; - address public immutable ammTreasuryWeEth; - address public immutable ammStorageWeEth; - address public immutable iporOracle; - - constructor( - address weEthInput, - address ipWeEthInput, - address ammTreasuryWeEthInput, - address ammStorageWeEthInput, - address iporOracleInput - ) { - weEth = weEthInput.checkAddress(); - ipWeEth = ipWeEthInput.checkAddress(); - ammTreasuryWeEth = ammTreasuryWeEthInput.checkAddress(); - ammStorageWeEth = ammStorageWeEthInput.checkAddress(); - iporOracle = iporOracleInput.checkAddress(); - } - - function getIpWeEthExchangeRate() external view returns (uint256) { - AmmTypes.AmmPoolCoreModel memory model = AmmTypes.AmmPoolCoreModel({ - asset: weEth, - assetDecimals: 18, - ipToken: ipWeEth, - ammStorage: ammStorageWeEth, - ammTreasury: ammTreasuryWeEth, - assetManagement: address(0), - iporOracle: iporOracle - }); - uint256 liquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryWeEth).getLiquidityPoolBalance(); - return model.getExchangeRate(liquidityPoolBalance); - } -} diff --git a/contracts/amm-weEth/interfaces/IAmmPoolsLensWeEth.sol b/contracts/amm-weEth/interfaces/IAmmPoolsLensWeEth.sol deleted file mode 100644 index 7a9e3c667..000000000 --- a/contracts/amm-weEth/interfaces/IAmmPoolsLensWeEth.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.26; - -/// @title Interface of the AmmPoolsLensWstEth contract. -interface IAmmPoolsLensWeEth { - /// @notice Retrieves the exchange rate between weEth and ipUsdm using the AmmLibEth library. - /// @return The exchange rate calculated based on the balance of weEth in the AMM Treasury and the total supply of ipUsdm. - /// @dev This function acts as a wrapper around the `getExchangeRate`. - function getIpWeEthExchangeRate() external view returns (uint256); -} diff --git a/contracts/amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol b/contracts/amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol index 77bdfe274..1b1b67e0b 100644 --- a/contracts/amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol +++ b/contracts/amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -/// @title Interface of the AmmPoolsServiceWstEth contract. +/// @title Interface of the AmmPoolsServiceWeEth contract. interface IAmmPoolsServiceWeEth { function provideLiquidityWeEthToAmmPoolWeEth(address beneficiary, uint256 weEthAmount) external; @@ -14,5 +14,7 @@ interface IAmmPoolsServiceWeEth { function redeemFromAmmPoolWeEth(address beneficiary, uint256 ipTokenAmount) external; + function rebalanceBetweenAmmTreasuryAndAssetManagementWeEth() external; + error ProvideLiquidityFailed(address poolAsset, string errorCode, string errorMessage); } diff --git a/contracts/amm-weEth/interfaces/IEEthLiquidityPool.sol b/contracts/amm-weEth/interfaces/IEEthLiquidityPool.sol index f718fe5b6..9697eb91d 100644 --- a/contracts/amm-weEth/interfaces/IEEthLiquidityPool.sol +++ b/contracts/amm-weEth/interfaces/IEEthLiquidityPool.sol @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; interface IEEthLiquidityPool { diff --git a/contracts/amm/AmmCloseSwapServiceStable.sol b/contracts/amm/AmmCloseSwapServiceStable.sol index 5f2852bf9..a87507381 100644 --- a/contracts/amm/AmmCloseSwapServiceStable.sol +++ b/contracts/amm/AmmCloseSwapServiceStable.sol @@ -567,7 +567,7 @@ abstract contract AmmCloseSwapServiceStable is IAmmCloseSwapService { IporTypes.AmmBalancesMemory memory balance = model.getAccruedBalance(); - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( poolCfg.asset ); diff --git a/contracts/amm/AmmPoolsService.sol b/contracts/amm/AmmPoolsService.sol index 51b473ae3..d9504087c 100644 --- a/contracts/amm/AmmPoolsService.sol +++ b/contracts/amm/AmmPoolsService.sol @@ -156,7 +156,7 @@ contract AmmPoolsService is IAmmPoolsService { AmmPoolsServicePoolConfiguration memory poolCfg = _getPoolConfiguration(asset); - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( poolCfg.asset ); @@ -206,7 +206,7 @@ contract AmmPoolsService is IAmmPoolsService { function _provideLiquidity(address asset, address beneficiary, uint256 assetAmount) internal { AmmPoolsServicePoolConfiguration memory poolCfg = _getPoolConfiguration(asset); - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( poolCfg.asset ); AmmTypes.AmmPoolCoreModel memory model; @@ -399,7 +399,7 @@ contract AmmPoolsService is IAmmPoolsService { function _rebalanceIfNeededAfterProvideLiquidity( AmmPoolsServicePoolConfiguration memory poolCfg, - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg, + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg, uint256 vaultBalance, uint256 wadOperationAmount ) internal { @@ -434,7 +434,7 @@ contract AmmPoolsService is IAmmPoolsService { uint256 vaultBalance, uint256 wadOperationAmount ) internal { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( poolCfg.asset ); diff --git a/contracts/amm-eth/AmmCloseSwapServiceStEth.sol b/contracts/base/amm-stEth/services/AmmCloseSwapServiceStEthBaseV2.sol similarity index 70% rename from contracts/amm-eth/AmmCloseSwapServiceStEth.sol rename to contracts/base/amm-stEth/services/AmmCloseSwapServiceStEthBaseV2.sol index 43e3e2530..245eac048 100644 --- a/contracts/amm-eth/AmmCloseSwapServiceStEth.sol +++ b/contracts/base/amm-stEth/services/AmmCloseSwapServiceStEthBaseV2.sol @@ -1,23 +1,26 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.26; -import "../interfaces/IAmmCloseSwapServiceStEth.sol"; -import "../base/amm/services/AmmCloseSwapServiceBaseV1.sol"; +import {IAmmCloseSwapServiceStEth} from "../../../interfaces/IAmmCloseSwapServiceStEth.sol"; +import {AmmCloseSwapServiceBaseV2} from "../../amm/services/AmmCloseSwapServiceBaseV2.sol"; + +import {IporContractValidator} from "../../../libraries/IporContractValidator.sol"; + +import {IAmmCloseSwapLens} from "../../../interfaces/IAmmCloseSwapLens.sol"; + +import {AmmTypes} from "../../../interfaces/types/AmmTypes.sol"; + +import {StorageLibBaseV1} from "../../libraries/StorageLibBaseV1.sol"; + /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. /// @dev Service can be safely used directly only if you are sure that methods will not touch any storage variables. -contract AmmCloseSwapServiceStEth is AmmCloseSwapServiceBaseV1, IAmmCloseSwapServiceStEth { - using IporContractValidator for address; - - address public immutable messageSigner; +contract AmmCloseSwapServiceStEthBaseV2 is AmmCloseSwapServiceBaseV2, IAmmCloseSwapServiceStEth { constructor( IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg, - address iporOracleInput, - address messageSignerInput - ) AmmCloseSwapServiceBaseV1(poolCfg, iporOracleInput) { - messageSigner = messageSignerInput.checkAddress(); - } + address iporOracle_ + ) AmmCloseSwapServiceBaseV2(poolCfg, iporOracle_) {} function closeSwapsStEth( address beneficiary, @@ -60,6 +63,6 @@ contract AmmCloseSwapServiceStEth is AmmCloseSwapServiceBaseV1, IAmmCloseSwapSer } function _getMessageSigner() internal view override returns (address) { - return messageSigner; + return StorageLibBaseV1.getMessageSignerStorage().value; } } diff --git a/contracts/base/amm-weEth/interfaces/IAmmPoolsServiceWeEthBaseV1.sol b/contracts/base/amm-weEth/interfaces/IAmmPoolsServiceWeEthBaseV1.sol new file mode 100644 index 000000000..58cd5e8bc --- /dev/null +++ b/contracts/base/amm-weEth/interfaces/IAmmPoolsServiceWeEthBaseV1.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.26; + +/// @title Interface for the base AmmPoolsService for weETH with Asset Management support +interface IAmmPoolsServiceWeEthBaseV1 { + /// @notice Provides liquidity to the AMM pool using weETH tokens + /// @param beneficiary Address that will receive ipweETH tokens + /// @param weEthAmount Amount of weETH to deposit (in 18 decimals) + function provideLiquidityWeEth(address beneficiary, uint256 weEthAmount) external payable; + + /// @notice Redeems ipweETH tokens and receives weETH + /// @param beneficiary Address that will receive weETH tokens + /// @param ipTokenAmount Amount of ipweETH tokens to redeem + function redeemFromAmmPoolWeEth(address beneficiary, uint256 ipTokenAmount) external; + + /// @notice Rebalances assets between AMM Treasury and Asset Management (Plasma Vault) + /// @dev Can only be called by addresses appointed to rebalance + function rebalanceBetweenAmmTreasuryAndAssetManagementWeEth() external; +} diff --git a/contracts/base/amm-weEth/services/AmmPoolsServiceWeEthBaseV1.sol b/contracts/base/amm-weEth/services/AmmPoolsServiceWeEthBaseV1.sol new file mode 100644 index 000000000..1a2d05056 --- /dev/null +++ b/contracts/base/amm-weEth/services/AmmPoolsServiceWeEthBaseV1.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.26; + +import {IAmmPoolsServiceWeEthBaseV1} from "../interfaces/IAmmPoolsServiceWeEthBaseV1.sol"; +import {AmmPoolsServiceBaseV1} from "../../amm/services/AmmPoolsServiceBaseV1.sol"; + +/// @title Base contract for AMM Pools Service for weETH with Asset Management support +/// @notice Supports providing liquidity with weETH and includes auto-rebalancing between AMM Treasury and Asset Management (Plasma Vault) +/// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. +/// @dev Asset Management is supported in this contract. Rebalancing between AMM Treasury and Asset Management IS supported in this contract. +contract AmmPoolsServiceWeEthBaseV1 is IAmmPoolsServiceWeEthBaseV1, AmmPoolsServiceBaseV1 { + constructor( + address weEth_, + address ipToken_, + address ammTreasury_, + address ammStorage_, + address ammAssetManagement_, + address iporOracle_, + address iporProtocolRouter_, + uint256 redeemFeeRate_, + uint256 autoRebalanceThresholdMultiplier_ + ) + AmmPoolsServiceBaseV1( + weEth_, + ipToken_, + ammTreasury_, + ammStorage_, + ammAssetManagement_, + iporOracle_, + iporProtocolRouter_, + redeemFeeRate_, + autoRebalanceThresholdMultiplier_ + ) + {} + + /// @notice Provides liquidity to the AMM pool using weETH tokens + /// @param beneficiary Address that will receive ipweETH tokens + /// @param weEthAmount Amount of weETH to deposit (in 18 decimals) + function provideLiquidityWeEth(address beneficiary, uint256 weEthAmount) external payable virtual override { + _provideLiquidity(beneficiary, weEthAmount); + } + + /// @notice Redeems ipweETH tokens and receives weETH + /// @param beneficiary Address that will receive weETH tokens + /// @param ipTokenAmount Amount of ipweETH tokens to redeem + function redeemFromAmmPoolWeEth(address beneficiary, uint256 ipTokenAmount) external virtual override { + _redeem(beneficiary, ipTokenAmount); + } + + /// @notice Rebalances assets between AMM Treasury and Asset Management (Plasma Vault) + /// @dev Can only be called by addresses appointed to rebalance + function rebalanceBetweenAmmTreasuryAndAssetManagementWeEth() external virtual override { + _rebalanceBetweenAmmTreasuryAndAssetManagement(); + } +} diff --git a/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV1.sol b/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV1.sol index 56cf57b9a..dbdf48154 100644 --- a/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV1.sol +++ b/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV1.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -/// @title Interface of the AmmPoolsServiceWstEth contract. +/// @title Interface of the AmmPoolsServiceWstEthBaseV1 contract. interface IAmmPoolsServiceWstEthBaseV1 { /// @notice Provides liquidity to the AMM pool. Provide wstETH asset to wstETH Pool. /// @param beneficiary The address of the beneficiary. diff --git a/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol b/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol index 6c3bdb73a..8dba9fd8d 100644 --- a/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol +++ b/contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; import {IAmmPoolsServiceWstEthBaseV1} from "./IAmmPoolsServiceWstEthBaseV1.sol"; -/// @title Interface of the AmmPoolsServiceWstEth contract V2 which supports rebalancing between AmmTreasury and AssetManagement. +/// @title Interface of the AmmPoolsServiceWstEthBaseV2 contract V2 which supports rebalancing between AmmTreasury and AssetManagement. interface IAmmPoolsServiceWstEthBaseV2 is IAmmPoolsServiceWstEthBaseV1 { /// @notice Rebalances wstETH assets between the AmmTreasury and the AssetManagement, based on configuration stored /// in the `AmmPoolsParamsValue.ammTreasuryAndAssetManagementRatio` field. diff --git a/contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV1.sol b/contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV1.sol index 22690d4a7..d1f355420 100644 --- a/contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV1.sol +++ b/contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV1.sol @@ -8,7 +8,6 @@ import "../../../interfaces/types/AmmTypes.sol"; import "../interfaces/IAmmPoolsServiceWstEthBaseV1.sol"; import "../../../libraries/errors/AmmErrors.sol"; import "../../../libraries/math/IporMath.sol"; -import "../../../libraries/StorageLib.sol"; import "../../../libraries/IporContractValidator.sol"; import "../../../libraries/AmmLib.sol"; import "../../../governance/AmmConfigurationManager.sol"; @@ -50,7 +49,7 @@ contract AmmPoolsServiceWstEthBaseV1 is IAmmPoolsServiceWstEthBaseV1 { } function provideLiquidityWstEth(address beneficiary, uint256 wstEthAmount) external payable override { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(wstEth); + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(wstEth); uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryWstEth).getLiquidityPoolBalance(); uint256 newPoolBalance = actualLiquidityPoolBalance + wstEthAmount; diff --git a/contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV2.sol b/contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV2.sol index 66dd4abfe..b306c1830 100644 --- a/contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV2.sol +++ b/contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV2.sol @@ -5,7 +5,7 @@ import {IAmmPoolsServiceWstEthBaseV2} from "../../../base/amm-wstEth/interfaces/ import {AmmPoolsServiceBaseV1} from "../../../base/amm/services/AmmPoolsServiceBaseV1.sol"; /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. -/// @dev Asset Management is supported in this contract. Rebalancing between AMM Treasury and Asset Management IS supported in this contract. +/// @dev Asset Management is supported in this contract. Rebalancing between AMM Treasury and Asset Management IS supported in this contract. contract AmmPoolsServiceWstEthBaseV2 is IAmmPoolsServiceWstEthBaseV2, AmmPoolsServiceBaseV1 { constructor( address asset_, diff --git a/contracts/base/amm/AmmTreasuryBaseV2.sol b/contracts/base/amm/AmmTreasuryBaseV2.sol index bc687682a..a770837b0 100644 --- a/contracts/base/amm/AmmTreasuryBaseV2.sol +++ b/contracts/base/amm/AmmTreasuryBaseV2.sol @@ -23,13 +23,13 @@ import "../../security/IporOwnableUpgradeable.sol"; /// @title AMM Treasury Base V2 support Asset Management which is ERC4626 Vault. contract AmmTreasuryBaseV2 is -Initializable, -PausableUpgradeable, -ReentrancyGuardUpgradeable, -UUPSUpgradeable, -IporOwnableUpgradeable, -IAmmTreasuryBaseV2, -IProxyImplementation + Initializable, + PausableUpgradeable, + ReentrancyGuardUpgradeable, + UUPSUpgradeable, + IporOwnableUpgradeable, + IAmmTreasuryBaseV2, + IProxyImplementation { using SafeCast for uint256; using SafeCast for int256; diff --git a/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol b/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol index 167d5551a..9a4c041d4 100644 --- a/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol +++ b/contracts/base/amm/services/AmmCloseSwapServiceBaseV2.sol @@ -78,7 +78,7 @@ abstract contract AmmCloseSwapServiceBaseV2 is AmmCloseSwapServiceBaseV1 { uint256 ammTreasuryErc20BalanceBeforeRedeem = IERC20Upgradeable(asset).balanceOf(ammTreasury); if (ammTreasuryErc20BalanceBeforeRedeem <= totalTransferAmountAssetDecimals) { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( asset ); diff --git a/contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol b/contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol index c9619471c..b57fcf9ff 100644 --- a/contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol @@ -221,7 +221,7 @@ contract AmmGovernanceServiceBaseV1 is } function getAmmPoolsParams(address asset) external view override returns (AmmPoolsParamsConfiguration memory cfg) { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(asset); + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(asset); cfg = AmmPoolsParamsConfiguration({ maxLiquidityPoolBalance: uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, autoRebalanceThreshold: ammPoolsParamsCfg.autoRebalanceThreshold, diff --git a/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol b/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol index 4ce57b9f8..1d2d2006d 100644 --- a/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol +++ b/contracts/base/amm/services/AmmPoolsServiceBaseV1.sol @@ -21,6 +21,7 @@ import "../../../governance/AmmConfigurationManager.sol"; /// @title Base contract for AMM pools service for Pools with one asset and Asset Management support with one underlying asset same as pool asset. /// @notice This contract is used for providing liquidity and redeeming liquidity from AMM pools including configured rebalancing between AMM Treasury and Asset Management (like Plasma Vault from Ipor Fusion). +/// @notice Support Asset Management (IPOR Fusion Vault) /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { using IporContractValidator for address; @@ -75,7 +76,9 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { } function _provideLiquidity(address beneficiary, uint256 assetAmount) internal virtual { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(asset); + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + asset + ); uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV2(ammTreasury).getLiquidityPoolBalance(); @@ -99,7 +102,7 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { /// @dev Order of the following two functions is important, first safeTransferFrom, then rebalanceIfNeededAfterProvideLiquidity. _rebalanceIfNeededAfterProvideLiquidity(ammPoolsParamsCfg, wadAssetAmount); - emit ProvideLiquidity(asset, msg.sender, beneficiary, ammTreasury, exchangeRate, wadAssetAmount, ipTokenAmount); + _emitProvideLiquidityEvent(beneficiary, exchangeRate, wadAssetAmount, ipTokenAmount); } function _redeem(address beneficiary, uint256 ipTokenAmount) internal virtual { @@ -130,16 +133,7 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { IERC20Upgradeable(asset).safeTransferFrom(ammTreasury, beneficiary, amountToRedeem); - emit Redeem( - asset, - ammTreasury, - msg.sender, - beneficiary, - exchangeRate, - wadAssetAmount, - wadAmountToRedeem, - ipTokenAmount - ); + _emitRedeemEvent(beneficiary, exchangeRate, wadAssetAmount, wadAmountToRedeem, ipTokenAmount); } function _rebalanceBetweenAmmTreasuryAndAssetManagement() internal virtual { @@ -148,7 +142,9 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { AmmPoolsErrors.CALLER_NOT_APPOINTED_TO_REBALANCE ); - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(asset); + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + asset + ); uint256 wadAmmTreasuryAssetBalance = IporMath.convertToWad( IERC20Upgradeable(asset).balanceOf(ammTreasury), @@ -164,17 +160,17 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { /// @dev 1e14 explanation: ammTreasuryAndAssetManagementRatio represents percentage in 2 decimals, example 45% = 4500, so to achieve number in 18 decimals we need to multiply by 1e14 uint256 ammTreasuryAssetManagementBalanceRatio = uint256(ammPoolsParamsCfg.ammTreasuryAndAssetManagementRatio) * - 1e14; + 1e14; if (ratio > ammTreasuryAssetManagementBalanceRatio) { uint256 wadAssetAmount = wadAmmTreasuryAssetBalance - - IporMath.division(ammTreasuryAssetManagementBalanceRatio * wadTotalBalance, 1e18); + IporMath.division(ammTreasuryAssetManagementBalanceRatio * wadTotalBalance, 1e18); if (wadAssetAmount > 0) { IAmmTreasuryBaseV2(ammTreasury).depositToAssetManagementInternal(wadAssetAmount); } } else { uint256 wadAssetAmount = IporMath.division(ammTreasuryAssetManagementBalanceRatio * wadTotalBalance, 1e18) - - wadAmmTreasuryAssetBalance; + wadAmmTreasuryAssetBalance; if (wadAssetAmount > 0) { IAmmTreasuryBaseV2(ammTreasury).withdrawFromAssetManagementInternal(wadAssetAmount); } @@ -195,7 +191,7 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { } function _rebalanceIfNeededAfterProvideLiquidity( - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg, + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg, uint256 wadOperationAmount ) internal { /// @dev 1e18 * autoRebalanceThresholdMultiplier explanation: autoRebalanceThreshold represents value without decimals, selected asset can have different multiplier, for example for stables is 1000x, value in thousands, for ETH, wstETH etc. is 1x @@ -224,7 +220,9 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { assetDecimals ); - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(asset); + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + asset + ); /// @dev 1e18 * autoRebalanceThresholdMultiplier explanation: autoRebalanceThreshold represents value without decimals, selected asset can have different multiplier, for example for stables is 1000x, value in thousands, for ETH, wstETH etc. is 1x uint256 autoRebalanceThreshold = uint256(ammPoolsParamsCfg.autoRebalanceThreshold) * @@ -245,8 +243,49 @@ contract AmmPoolsServiceBaseV1 is IProvideLiquidityEvents { ); if (rebalanceAmount < 0) { - IAmmTreasuryBaseV2(ammTreasury).withdrawFromAssetManagementInternal((- rebalanceAmount).toUint256()); + IAmmTreasuryBaseV2(ammTreasury).withdrawFromAssetManagementInternal((-rebalanceAmount).toUint256()); } } } + + /// @notice Virtual function to emit provide liquidity event, can be overridden by derived contracts + /// @dev Default implementation emits standard ProvideLiquidity event from IProvideLiquidityEvents + /// @param beneficiary Address that received ipTokens + /// @param exchangeRate Exchange rate used for minting + /// @param wadAssetAmount Amount of asset provided (in 18 decimals) + /// @param ipTokenAmount Amount of ipTokens minted + function _emitProvideLiquidityEvent( + address beneficiary, + uint256 exchangeRate, + uint256 wadAssetAmount, + uint256 ipTokenAmount + ) internal virtual { + emit ProvideLiquidity(asset, msg.sender, beneficiary, ammTreasury, exchangeRate, wadAssetAmount, ipTokenAmount); + } + + /// @notice Virtual function to emit redeem event, can be overridden by derived contracts + /// @dev Default implementation emits standard Redeem event from IProvideLiquidityEvents + /// @param beneficiary Address that received redeemed assets + /// @param exchangeRate Exchange rate used for redemption + /// @param wadAssetAmount Total asset amount before fee (in 18 decimals) + /// @param wadAmountToRedeem Asset amount after fee (in 18 decimals) + /// @param ipTokenAmount Amount of ipTokens burned + function _emitRedeemEvent( + address beneficiary, + uint256 exchangeRate, + uint256 wadAssetAmount, + uint256 wadAmountToRedeem, + uint256 ipTokenAmount + ) internal virtual { + emit Redeem( + asset, + ammTreasury, + msg.sender, + beneficiary, + exchangeRate, + wadAssetAmount, + wadAmountToRedeem, + ipTokenAmount + ); + } } diff --git a/contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol b/contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol index b61aee972..949628d5a 100644 --- a/contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol +++ b/contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol @@ -220,7 +220,7 @@ contract AmmGovernanceServiceArbitrum is } function getAmmPoolsParams(address asset) external view override returns (AmmPoolsParamsConfiguration memory cfg) { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(asset); + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(asset); cfg = AmmPoolsParamsConfiguration({ maxLiquidityPoolBalance: uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, autoRebalanceThreshold: ammPoolsParamsCfg.autoRebalanceThreshold, diff --git a/contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol b/contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol deleted file mode 100644 index 7dbd562d5..000000000 --- a/contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol +++ /dev/null @@ -1,43 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; - -import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; - -import "../../../libraries/AmmLib.sol"; -import {IAmmPoolsServiceUsdc} from "../interfaces/IAmmPoolsServiceUsdc.sol"; -import {AmmPoolsServiceBaseV1} from "../../../base/amm/services/AmmPoolsServiceBaseV1.sol"; - -/// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. -contract AmmPoolsServiceUsdc is IAmmPoolsServiceUsdc, AmmPoolsServiceBaseV1 { - constructor( - address asset_, - address ipToken_, - address ammTreasury_, - address ammStorage_, - address ammAssetManagement_, - address iporOracle_, - address iporProtocolRouter_, - uint256 redeemFeeRate_, - uint256 autoRebalanceThresholdMultiplier_ - ) - AmmPoolsServiceBaseV1( - asset_, - ipToken_, - ammTreasury_, - ammStorage_, - ammAssetManagement_, - iporOracle_, - iporProtocolRouter_, - redeemFeeRate_, - autoRebalanceThresholdMultiplier_ - ) - {} - - function provideLiquidityUsdcToAmmPoolUsdc(address beneficiary, uint256 assetAmount) external payable override { - _provideLiquidity(beneficiary, assetAmount); - } - - function redeemFromAmmPoolUsdc(address beneficiary, uint256 ipTokenAmount) external { - _redeem(beneficiary, ipTokenAmount); - } -} diff --git a/contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol b/contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol deleted file mode 100644 index 715f05131..000000000 --- a/contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; - -import "../../../interfaces/IAmmCloseSwapServiceWstEth.sol"; -import "../../../base/amm/services/AmmCloseSwapServiceBaseV1.sol"; -import {StorageLibArbitrum} from "../libraries/StorageLibArbitrum.sol"; - -/// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. -/// @dev Service can be safely used directly only if you are sure that methods will not touch any storage variables. -contract AmmCloseSwapServiceWstEth is AmmCloseSwapServiceBaseV1, IAmmCloseSwapServiceWstEth { - - constructor( - IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg, - address iporOracle_ - ) AmmCloseSwapServiceBaseV1(poolCfg, iporOracle_) {} - - function closeSwapsWstEth( - address beneficiary, - uint256[] memory payFixedSwapIds, - uint256[] memory receiveFixedSwapIds, - AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput - ) - external - override - returns ( - AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps, - AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps - ) - { - (closedPayFixedSwaps, closedReceiveFixedSwaps) = _closeSwaps( - beneficiary, - payFixedSwapIds, - receiveFixedSwapIds, - riskIndicatorsInput - ); - } - - function emergencyCloseSwapsWstEth( - uint256[] memory payFixedSwapIds, - uint256[] memory receiveFixedSwapIds, - AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput - ) - external - override - returns ( - AmmTypes.IporSwapClosingResult[] memory closedPayFixedSwaps, - AmmTypes.IporSwapClosingResult[] memory closedReceiveFixedSwaps - ) - { - (closedPayFixedSwaps, closedReceiveFixedSwaps) = _emergencyCloseSwaps( - payFixedSwapIds, - receiveFixedSwapIds, - riskIndicatorsInput - ); - } - - function _getMessageSigner() internal view override returns (address) { - return StorageLibArbitrum.getMessageSignerStorage().value; - } -} diff --git a/contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol b/contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol deleted file mode 100644 index cc0d3797a..000000000 --- a/contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol +++ /dev/null @@ -1,190 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity 0.8.26; -import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; - -import "../../../interfaces/IAmmOpenSwapServiceWstEth.sol"; -import "../../../base/amm/services/AmmOpenSwapServiceBaseV1.sol"; -import {StorageLibArbitrum} from "../libraries/StorageLibArbitrum.sol"; - -/// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. -/// @dev Service can be safely used directly only if you are sure that methods will not touch any storage variables. -contract AmmOpenSwapServiceWstEth is AmmOpenSwapServiceBaseV1, IAmmOpenSwapServiceWstEth { - using SafeERC20Upgradeable for IERC20Upgradeable; - - modifier onlySupportedInputAsset(address inputAsset) { - if (inputAsset == asset) { - _; - } else { - revert IporErrors.UnsupportedAsset(IporErrors.INPUT_ASSET_NOT_SUPPORTED, inputAsset); - } - } - - constructor( - AmmTypesBaseV1.AmmOpenSwapServicePoolConfiguration memory poolCfg, - address iporOracle_ - ) AmmOpenSwapServiceBaseV1(poolCfg, iporOracle_) {} - - function openSwapPayFixed28daysWstEth( - address beneficiary, - address inputAsset, - uint256 inputAssetTotalAmount, - uint256 acceptableFixedInterestRate, - uint256 leverage, - AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs - ) external override onlySupportedInputAsset(inputAsset) returns (uint256) { - return - _openSwapPayFixed( - beneficiary, - inputAsset, - inputAssetTotalAmount, - IporTypes.SwapTenor.DAYS_28, - acceptableFixedInterestRate, - leverage, - riskIndicatorsInputs - ); - } - - function openSwapPayFixed60daysWstEth( - address beneficiary, - address inputAsset, - uint256 inputAssetTotalAmount, - uint256 acceptableFixedInterestRate, - uint256 leverage, - AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs - ) external override onlySupportedInputAsset(inputAsset) returns (uint256) { - return - _openSwapPayFixed( - beneficiary, - inputAsset, - inputAssetTotalAmount, - IporTypes.SwapTenor.DAYS_60, - acceptableFixedInterestRate, - leverage, - riskIndicatorsInputs - ); - } - - function openSwapPayFixed90daysWstEth( - address beneficiary, - address inputAsset, - uint256 inputAssetTotalAmount, - uint256 acceptableFixedInterestRate, - uint256 leverage, - AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs - ) external override onlySupportedInputAsset(inputAsset) returns (uint256) { - return - _openSwapPayFixed( - beneficiary, - inputAsset, - inputAssetTotalAmount, - IporTypes.SwapTenor.DAYS_90, - acceptableFixedInterestRate, - leverage, - riskIndicatorsInputs - ); - } - - function openSwapReceiveFixed28daysWstEth( - address beneficiary, - address inputAsset, - uint256 inputAssetTotalAmount, - uint256 acceptableFixedInterestRate, - uint256 leverage, - AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs - ) external override onlySupportedInputAsset(inputAsset) returns (uint256) { - return - _openSwapReceiveFixed( - beneficiary, - inputAsset, - inputAssetTotalAmount, - IporTypes.SwapTenor.DAYS_28, - acceptableFixedInterestRate, - leverage, - riskIndicatorsInputs - ); - } - - function openSwapReceiveFixed60daysWstEth( - address beneficiary, - address inputAsset, - uint256 inputAssetTotalAmount, - uint256 acceptableFixedInterestRate, - uint256 leverage, - AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs - ) external override onlySupportedInputAsset(inputAsset) returns (uint256) { - return - _openSwapReceiveFixed( - beneficiary, - inputAsset, - inputAssetTotalAmount, - IporTypes.SwapTenor.DAYS_60, - acceptableFixedInterestRate, - leverage, - riskIndicatorsInputs - ); - } - - function openSwapReceiveFixed90daysWstEth( - address beneficiary, - address inputAsset, - uint256 inputAssetTotalAmount, - uint256 acceptableFixedInterestRate, - uint256 leverage, - AmmTypes.RiskIndicatorsInputs calldata riskIndicatorsInputs - ) external override onlySupportedInputAsset(inputAsset) returns (uint256) { - return - _openSwapReceiveFixed( - beneficiary, - inputAsset, - inputAssetTotalAmount, - IporTypes.SwapTenor.DAYS_90, - acceptableFixedInterestRate, - leverage, - riskIndicatorsInputs - ); - } - - function _getMessageSigner() internal view override returns (address) { - return StorageLibArbitrum.getMessageSignerStorage().value; - } - - function _convertToAssetAmount( - address inputAsset, - uint256 inputAssetAmount - ) internal pure override returns (uint256) { - /// @dev we supported only wstETH - return inputAssetAmount; - } - - function _convertInputAssetAmountToWadAmount( - address, - uint256 inputAssetAmount - ) internal pure override returns (uint256) { - /// @dev wstETH is represented in 18 decimals so no conversion is needed - return inputAssetAmount; - } - - function _validateInputAsset(address inputAsset, uint256 inputAssetTotalAmount) internal view override { - if (inputAssetTotalAmount == 0) { - revert IporErrors.InputAssetTotalAmountTooLow( - IporErrors.SENDER_ASSET_BALANCE_TOO_LOW, - inputAssetTotalAmount - ); - } - - uint256 accountBalance = IERC20Upgradeable(inputAsset).balanceOf(msg.sender); - - if (accountBalance < inputAssetTotalAmount) { - revert IporErrors.InputAssetBalanceTooLow( - IporErrors.SENDER_ASSET_BALANCE_TOO_LOW, - inputAsset, - accountBalance, - inputAssetTotalAmount - ); - } - } - - function _transferTotalAmountToAmmTreasury(address inputAsset, uint256 inputAssetTotalAmount) internal override { - IERC20Upgradeable(asset).safeTransferFrom(msg.sender, ammTreasury, inputAssetTotalAmount); - } -} diff --git a/contracts/chains/arbitrum/amm-wstEth/AmmPoolsServiceWstEth.sol b/contracts/chains/arbitrum/amm-wstEth/AmmPoolsServiceWstEth.sol index 516b5d07e..fdb8d119f 100644 --- a/contracts/chains/arbitrum/amm-wstEth/AmmPoolsServiceWstEth.sol +++ b/contracts/chains/arbitrum/amm-wstEth/AmmPoolsServiceWstEth.sol @@ -1,124 +1,70 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.26; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "../../../interfaces/IIpToken.sol"; -import "../../../interfaces/types/AmmTypes.sol"; -import "../interfaces/IAmmPoolsServiceWstEth.sol"; -import "../../../libraries/errors/AmmErrors.sol"; -import "../../../libraries/math/IporMath.sol"; -import "../../../libraries/StorageLib.sol"; -import "../../../libraries/IporContractValidator.sol"; -import "../../../libraries/AmmLib.sol"; -import "../../../governance/AmmConfigurationManager.sol"; -import "../../../base/interfaces/IAmmTreasuryBaseV1.sol"; +import {IAmmPoolsServiceWstEth} from "../interfaces/IAmmPoolsServiceWstEth.sol"; +import {AmmPoolsServiceWstEthBaseV2} from "../../../base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV2.sol"; /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. -contract AmmPoolsServiceWstEth is IAmmPoolsServiceWstEth { - using IporContractValidator for address; - using SafeERC20 for IERC20; - using AmmLib for AmmTypes.AmmPoolCoreModel; - - address public immutable wstEth; - address public immutable ipwstEth; - address public immutable ammTreasuryWstEth; - address public immutable ammStorageWstEth; - address public immutable iporOracle; - address public immutable iporProtocolRouter; - uint256 public immutable redeemFeeRateWstEth; - +/// @dev This contract extends AmmPoolsServiceWstEthBaseV2 with Asset Management support. +/// @dev Asset Management is supported in this contract. Rebalancing between AMM Treasury and Asset Management IS supported in this contract. +contract AmmPoolsServiceWstEth is AmmPoolsServiceWstEthBaseV2 { constructor( address wstEthInput, address ipwstEthInput, address ammTreasuryWstEthInput, address ammStorageWstEthInput, + address ammAssetManagementInput, address iporOracleInput, address iporProtocolRouterInput, - uint256 redeemFeeRateWstEthInput - ) { - wstEth = wstEthInput.checkAddress(); - ipwstEth = ipwstEthInput.checkAddress(); - ammTreasuryWstEth = ammTreasuryWstEthInput.checkAddress(); - ammStorageWstEth = ammStorageWstEthInput.checkAddress(); - iporOracle = iporOracleInput.checkAddress(); - iporProtocolRouter = iporProtocolRouterInput.checkAddress(); - redeemFeeRateWstEth = redeemFeeRateWstEthInput; - - require(redeemFeeRateWstEthInput <= 1e18, AmmPoolsErrors.CFG_INVALID_REDEEM_FEE_RATE); - } - - function provideLiquidityWstEth(address beneficiary, uint256 wstEthAmount) external payable override { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(wstEth); - - uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryWstEth).getLiquidityPoolBalance(); - uint256 newPoolBalance = actualLiquidityPoolBalance + wstEthAmount; - - require( - newPoolBalance <= uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, - AmmErrors.LIQUIDITY_POOL_BALANCE_IS_TOO_HIGH - ); - - uint256 exchangeRate = _getExchangeRate(actualLiquidityPoolBalance); - - IERC20(wstEth).safeTransferFrom(msg.sender, ammTreasuryWstEth, wstEthAmount); - - uint256 ipTokenAmount = IporMath.division(wstEthAmount * 1e18, exchangeRate); - - IIpToken(ipwstEth).mint(beneficiary, ipTokenAmount); - + uint256 redeemFeeRateWstEthInput, + uint256 autoRebalanceThresholdMultiplier_ + ) + AmmPoolsServiceWstEthBaseV2( + wstEthInput, + ipwstEthInput, + ammTreasuryWstEthInput, + ammStorageWstEthInput, + ammAssetManagementInput, + iporOracleInput, + iporProtocolRouterInput, + redeemFeeRateWstEthInput, + autoRebalanceThresholdMultiplier_ + ) + {} + + /// @notice Override to emit Arbitrum-specific ProvideLiquidityWstEth event + function _emitProvideLiquidityEvent( + address beneficiary, + uint256 exchangeRate, + uint256 wadAssetAmount, + uint256 ipTokenAmount + ) internal virtual override { emit IAmmPoolsServiceWstEth.ProvideLiquidityWstEth( msg.sender, beneficiary, - ammTreasuryWstEth, + ammTreasury, exchangeRate, - wstEthAmount, + wadAssetAmount, ipTokenAmount ); } - function redeemFromAmmPoolWstEth(address beneficiary, uint256 ipTokenAmount) external { - require( - ipTokenAmount > 0 && ipTokenAmount <= IIpToken(ipwstEth).balanceOf(msg.sender), - AmmPoolsErrors.CANNOT_REDEEM_IP_TOKEN_TOO_LOW - ); - require(beneficiary != address(0), IporErrors.WRONG_ADDRESS); - - uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryWstEth).getLiquidityPoolBalance(); - - uint256 exchangeRate = _getExchangeRate(actualLiquidityPoolBalance); - - uint256 wstEthAmount = IporMath.division(ipTokenAmount * exchangeRate, 1e18); - - uint256 amountToRedeem = IporMath.division(wstEthAmount * (1e18 - redeemFeeRateWstEth), 1e18); - - require(amountToRedeem > 0, AmmPoolsErrors.CANNOT_REDEEM_ASSET_AMOUNT_TOO_LOW); - - IIpToken(ipwstEth).burn(msg.sender, ipTokenAmount); - - IERC20(wstEth).safeTransferFrom(ammTreasuryWstEth, beneficiary, amountToRedeem); - - emit RedeemWstEth( - ammTreasuryWstEth, + /// @notice Override to emit Arbitrum-specific RedeemWstEth event + function _emitRedeemEvent( + address beneficiary, + uint256 exchangeRate, + uint256 wadAssetAmount, + uint256 wadAmountToRedeem, + uint256 ipTokenAmount + ) internal virtual override { + emit IAmmPoolsServiceWstEth.RedeemWstEth( + ammTreasury, msg.sender, beneficiary, exchangeRate, - wstEthAmount, - amountToRedeem, + wadAssetAmount, + wadAmountToRedeem, ipTokenAmount ); } - - function _getExchangeRate(uint256 actualLiquidityPoolBalance) internal view returns (uint256) { - AmmTypes.AmmPoolCoreModel memory model = AmmTypes.AmmPoolCoreModel({ - asset: wstEth, - assetDecimals: 18, - ipToken: ipwstEth, - ammStorage: ammStorageWstEth, - ammTreasury: ammTreasuryWstEth, - assetManagement: address(0), - iporOracle: iporOracle - }); - return model.getExchangeRate(actualLiquidityPoolBalance); - } } diff --git a/contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol b/contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol index 00d2e4426..e76595e37 100644 --- a/contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol +++ b/contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol @@ -13,9 +13,11 @@ import {IAmmGovernanceServiceArbitrum} from "../interfaces/IAmmGovernanceService import {IAmmGovernanceLensArbitrum} from "../interfaces/IAmmGovernanceLensArbitrum.sol"; import {IAmmPoolsLensArbitrum} from "../amm-commons/AmmPoolsLensArbitrum.sol"; import {IAmmPoolsServiceWstEth} from "../interfaces/IAmmPoolsServiceWstEth.sol"; +import {IAmmPoolsServiceWstEthBaseV2} from "../../../base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol"; import {IAmmOpenSwapServiceWstEth} from "../../../interfaces/IAmmOpenSwapServiceWstEth.sol"; import {IAmmCloseSwapServiceWstEth} from "../../../interfaces/IAmmCloseSwapServiceWstEth.sol"; import {IAmmPoolsServiceUsdc} from "../interfaces/IAmmPoolsServiceUsdc.sol"; +import {IAmmPoolsServiceUsdcBaseV1} from "../../../base/amm-usdc/interfaces/IAmmPoolsServiceUsdcBaseV1.sol"; import {IAmmOpenSwapServiceUsdc} from "../interfaces/IAmmOpenSwapServiceUsdc.sol"; import {IAmmCloseSwapServiceUsdc} from "../../../interfaces/IAmmCloseSwapServiceUsdc.sol"; import {IAmmPoolsServiceUsdm} from "../../../amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol"; @@ -119,7 +121,11 @@ contract IporProtocolRouterArbitrum is IporProtocolRouterAbstract { return servicesCfg.ammCloseSwapService; } else if ( _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWstEth.provideLiquidityWstEth.selector) || - _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWstEth.redeemFromAmmPoolWstEth.selector) + _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWstEth.redeemFromAmmPoolWstEth.selector) || + _checkFunctionSigAndIsNotPause( + sig, + IAmmPoolsServiceWstEthBaseV2.rebalanceBetweenAmmTreasuryAndAssetManagementWstEth.selector + ) ) { if (batchOperation == 0) { _nonReentrantBefore(); @@ -141,7 +147,11 @@ contract IporProtocolRouterArbitrum is IporProtocolRouterAbstract { return servicesCfg.ammPoolsService; } else if ( _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceUsdc.provideLiquidityUsdcToAmmPoolUsdc.selector) || - _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceUsdc.redeemFromAmmPoolUsdc.selector) + _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceUsdc.redeemFromAmmPoolUsdc.selector) || + _checkFunctionSigAndIsNotPause( + sig, + IAmmPoolsServiceUsdcBaseV1.rebalanceBetweenAmmTreasuryAndAssetManagementUsdc.selector + ) ) { if (batchOperation == 0) { _nonReentrantBefore(); diff --git a/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol b/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol index a7eba2dc8..89cafcbec 100644 --- a/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol +++ b/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol @@ -6,82 +6,41 @@ import "../../../interfaces/types/AmmTypes.sol"; import "../../../interfaces/IIporOracle.sol"; import "../../../interfaces/IAmmCloseSwapLens.sol"; import "../../../interfaces/IAmmCloseSwapService.sol"; +import "../../../interfaces/IAmmStorage.sol"; import "../../../libraries/errors/IporErrors.sol"; import "../../../libraries/IporContractValidator.sol"; import "../../../libraries/AmmCloseSwapServicePoolConfigurationLib.sol"; -import "../../../amm/libraries/SwapCloseLogicLib.sol"; -import "../../../base/types/AmmTypesBaseV1.sol"; import "../../../base/amm/libraries/SwapLogicBaseV1.sol"; import "../../../base/amm/libraries/SwapCloseLogicLibBaseV1.sol"; -import "../../../base/amm/services/AmmCloseSwapServiceBaseV1.sol"; +import "../../../amm/libraries/SwapCloseLogicLib.sol"; +import "../../../base/types/AmmTypesBaseV1.sol"; +import {StorageLibBaseV1} from "../../../base/libraries/StorageLibBaseV1.sol"; +/// @dev Legacy AmmCloseSwapLens for DAI/USDT/USDC which uses legacy SwapCloseLogicLib (not BaseV1) /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. contract AmmCloseSwapLens is IAmmCloseSwapLens { using IporContractValidator for address; - using SwapLogicBaseV1 for AmmTypesBaseV1.Swap; using AmmCloseSwapServicePoolConfigurationLib for IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration; - address public immutable usdt; - address public immutable usdc; - address public immutable dai; - address public immutable stETH; - address public immutable iporOracle; address public immutable messageSigner; address public immutable spreadRouter; - /// @dev Notice! Don't use following service to get data from storage, use only to get configuration stored in immutable fields. - address public immutable closeSwapServiceUsdt; - /// @dev Notice! Don't use following service to get data from storage, use only to get configuration stored in immutable fields. - address public immutable closeSwapServiceUsdc; - /// @dev Notice! Don't use following service to get data from storage, use only to get configuration stored in immutable fields. - address public immutable closeSwapServiceDai; - /// @dev Notice! Don't use following service to get data from storage, use only to get configuration stored in immutable fields. - address public immutable closeSwapServiceStEth; - - constructor( - address usdtInput, - address usdcInput, - address daiInput, - address stETHInput, - address iporOracleInput, - address messageSignerInput, - address spreadRouterInput, - address closeSwapServiceUsdtInput, - address closeSwapServiceUsdcInput, - address closeSwapServiceDaiInput, - address closeSwapServiceStEthInput - ) { - usdt = usdtInput.checkAddress(); - usdc = usdcInput.checkAddress(); - dai = daiInput.checkAddress(); - stETH = stETHInput.checkAddress(); - - iporOracle = iporOracleInput.checkAddress(); - messageSigner = messageSignerInput.checkAddress(); - spreadRouter = spreadRouterInput.checkAddress(); - - closeSwapServiceUsdt = closeSwapServiceUsdtInput.checkAddress(); - closeSwapServiceUsdc = closeSwapServiceUsdcInput.checkAddress(); - closeSwapServiceDai = closeSwapServiceDaiInput.checkAddress(); - closeSwapServiceStEth = closeSwapServiceStEthInput.checkAddress(); + constructor(address iporOracle_, address messageSigner_, address spreadRouter_) { + iporOracle = iporOracle_.checkAddress(); + messageSigner = messageSigner_.checkAddress(); + spreadRouter = spreadRouter_.checkAddress(); } function getAmmCloseSwapServicePoolConfiguration( address asset ) external view override returns (AmmCloseSwapServicePoolConfiguration memory) { - return _getPoolConfiguration(asset); - } + StorageLibBaseV1.AssetServicesValue memory servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + asset + ]; - function _getPoolConfiguration(address asset) internal view returns (AmmCloseSwapServicePoolConfiguration memory) { - if (asset == usdt) { - return IAmmCloseSwapService(closeSwapServiceUsdt).getPoolConfiguration(); - } else if (asset == usdc) { - return IAmmCloseSwapService(closeSwapServiceUsdc).getPoolConfiguration(); - } else if (asset == dai) { - return IAmmCloseSwapService(closeSwapServiceDai).getPoolConfiguration(); - } else if (asset == stETH) { - return IAmmCloseSwapService(closeSwapServiceStEth).getPoolConfiguration(); + if (servicesCfg.ammCloseSwapService != address(0)) { + return IAmmCloseSwapService(servicesCfg.ammCloseSwapService).getPoolConfiguration(); } else { revert IporErrors.UnsupportedAsset(IporErrors.ASSET_NOT_SUPPORTED, asset); } @@ -95,37 +54,17 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { uint256 closeTimestamp, AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput ) external view override returns (AmmTypes.ClosingSwapDetails memory closingSwapDetails) { - if (asset == usdt || asset == usdc || asset == dai) { - closingSwapDetails = _getClosingSwapDetailsForStable( - asset, - account, - direction, - swapId, - closeTimestamp, - riskIndicatorsInput - ); - } else if (asset == stETH) { - closingSwapDetails = _getClosingSwapDetailsForStEth( - account, - direction, - swapId, - closeTimestamp, - riskIndicatorsInput - ); - } else { + StorageLibBaseV1.AssetServicesValue memory servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + asset + ]; + + if (servicesCfg.ammCloseSwapService == address(0)) { revert IporErrors.UnsupportedAsset(IporErrors.ASSET_NOT_SUPPORTED, asset); } - } - function _getClosingSwapDetailsForStable( - address asset, - address account, - AmmTypes.SwapDirection direction, - uint256 swapId, - uint256 closeTimestamp, - AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput - ) internal view returns (AmmTypes.ClosingSwapDetails memory closingSwapDetails) { - AmmCloseSwapServicePoolConfiguration memory poolCfg = _getPoolConfiguration(asset); + IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg = IAmmCloseSwapService( + servicesCfg.ammCloseSwapService + ).getPoolConfiguration(); IporTypes.AccruedIpor memory accruedIpor = IIporOracle(iporOracle).getAccruedIndex( block.timestamp, @@ -137,7 +76,6 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { require(swap.id > 0, AmmErrors.INCORRECT_SWAP_ID); int256 swapPnlValueToDate; - if (direction == AmmTypes.SwapDirection.PAY_FIXED_RECEIVE_FLOATING) { swapPnlValueToDate = SwapLogicBaseV1.calculatePnlPayFixed( swap.openTimestamp, @@ -148,7 +86,7 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { block.timestamp, accruedIpor.ibtPrice ); - } else if (direction == AmmTypes.SwapDirection.PAY_FLOATING_RECEIVE_FIXED) { + } else { swapPnlValueToDate = SwapLogicBaseV1.calculatePnlReceiveFixed( swap.openTimestamp, swap.collateral, @@ -158,8 +96,6 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { block.timestamp, accruedIpor.ibtPrice ); - } else { - revert(AmmErrors.UNSUPPORTED_DIRECTION); } (closingSwapDetails.closableStatus, closingSwapDetails.swapUnwindRequired) = SwapCloseLogicLibBaseV1 @@ -214,80 +150,4 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { closingSwapDetails.pnlValue = swapPnlValueToDate; } } - - function _getClosingSwapDetailsForStEth( - address account, - AmmTypes.SwapDirection direction, - uint256 swapId, - uint256 closeTimestamp, - AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput - ) internal view returns (AmmTypes.ClosingSwapDetails memory closingSwapDetails) { - IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg = AmmCloseSwapServiceBaseV1( - closeSwapServiceStEth - ).getPoolConfiguration(); - - IporTypes.AccruedIpor memory accruedIpor = IIporOracle(iporOracle).getAccruedIndex( - block.timestamp, - poolCfg.asset - ); - - AmmTypesBaseV1.Swap memory swap = IAmmStorageBaseV1(poolCfg.ammStorage).getSwap(direction, swapId); - - require(swap.id > 0, AmmErrors.INCORRECT_SWAP_ID); - - int256 swapPnlValueToDate = swap.calculatePnl(block.timestamp, accruedIpor.ibtPrice); - - (closingSwapDetails.closableStatus, closingSwapDetails.swapUnwindRequired) = SwapCloseLogicLibBaseV1 - .getClosableStatusForSwap( - AmmTypesBaseV1.ClosableSwapInput({ - account: account, - asset: poolCfg.asset, - closeTimestamp: closeTimestamp, - swapBuyer: swap.buyer, - swapOpenTimestamp: swap.openTimestamp, - swapCollateral: swap.collateral, - swapTenor: swap.tenor, - swapState: swap.state, - swapPnlValueToDate: swapPnlValueToDate, - minLiquidationThresholdToCloseBeforeMaturityByCommunity: poolCfg - .minLiquidationThresholdToCloseBeforeMaturityByCommunity, - minLiquidationThresholdToCloseBeforeMaturityByBuyer: poolCfg - .minLiquidationThresholdToCloseBeforeMaturityByBuyer, - timeBeforeMaturityAllowedToCloseSwapByCommunity: poolCfg - .timeBeforeMaturityAllowedToCloseSwapByCommunity, - timeBeforeMaturityAllowedToCloseSwapByBuyer: poolCfg.getTimeBeforeMaturityAllowedToCloseSwapByBuyer( - swap.tenor - ), - timeAfterOpenAllowedToCloseSwapWithUnwinding: poolCfg - .getTimeAfterOpenAllowedToCloseSwapWithUnwinding(swap.tenor) - }) - ); - - if (closingSwapDetails.swapUnwindRequired == true) { - ( - closingSwapDetails.swapUnwindPnlValue, - closingSwapDetails.swapUnwindOpeningFeeAmount, - closingSwapDetails.swapUnwindFeeLPAmount, - closingSwapDetails.swapUnwindFeeTreasuryAmount, - closingSwapDetails.pnlValue - ) = SwapCloseLogicLibBaseV1.calculateSwapUnwindWhenUnwindRequired( - AmmTypesBaseV1.UnwindParams({ - asset: poolCfg.asset, - messageSigner: messageSigner, - spread: poolCfg.spread, - ammStorage: poolCfg.ammStorage, - ammTreasury: poolCfg.ammTreasury, - closeTimestamp: closeTimestamp, - swapPnlValueToDate: swapPnlValueToDate, - indexValue: accruedIpor.indexValue, - swap: swap, - unwindingFeeRate: poolCfg.unwindingFeeRate, - unwindingFeeTreasuryPortionRate: poolCfg.unwindingFeeTreasuryPortionRate, - riskIndicatorsInputs: riskIndicatorsInput - }) - ); - } else { - closingSwapDetails.pnlValue = swapPnlValueToDate; - } - } } diff --git a/contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol b/contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol deleted file mode 100644 index 3eb91a85f..000000000 --- a/contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol +++ /dev/null @@ -1,362 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -pragma solidity 0.8.26; - -import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; - -import "../../../interfaces/IAmmTreasury.sol"; -import "../../../interfaces/IAmmStorage.sol"; -import "../../../interfaces/IAmmGovernanceService.sol"; -import "../../../interfaces/IAmmGovernanceLens.sol"; -import "../../../libraries/math/IporMath.sol"; -import "../../../libraries/errors/AmmPoolsErrors.sol"; -import "../../../libraries/IporContractValidator.sol"; -import "../../../governance/AmmConfigurationManager.sol"; - -/// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. -contract AmmGovernanceService is IAmmGovernanceService, IAmmGovernanceLens { - using IporContractValidator for address; - using SafeERC20Upgradeable for IERC20Upgradeable; - - address internal immutable _usdt; - uint256 internal immutable _usdtDecimals; - address internal immutable _usdtAmmStorage; - address internal immutable _usdtAmmTreasury; - address internal immutable _usdtAmmVault; - address internal immutable _usdtAmmPoolsTreasury; - address internal immutable _usdtAmmPoolsTreasuryManager; - address internal immutable _usdtAmmCharlieTreasury; - address internal immutable _usdtAmmCharlieTreasuryManager; - - address internal immutable _usdc; - uint256 internal immutable _usdcDecimals; - address internal immutable _usdcAmmStorage; - address internal immutable _usdcAmmTreasury; - address internal immutable _usdcAmmVault; - address internal immutable _usdcAmmPoolsTreasury; - address internal immutable _usdcAmmPoolsTreasuryManager; - address internal immutable _usdcAmmCharlieTreasury; - address internal immutable _usdcAmmCharlieTreasuryManager; - - address internal immutable _dai; - uint256 internal immutable _daiDecimals; - address internal immutable _daiAmmStorage; - address internal immutable _daiAmmTreasury; - address internal immutable _daiAmmVault; - address internal immutable _daiAmmPoolsTreasury; - address internal immutable _daiAmmPoolsTreasuryManager; - address internal immutable _daiAmmCharlieTreasury; - address internal immutable _daiAmmCharlieTreasuryManager; - - address internal immutable _stEth; - uint256 internal immutable _stEthDecimals; - address internal immutable _stEthAmmStorage; - address internal immutable _stEthAmmTreasury; - address internal immutable _stEthAmmPoolsTreasury; - address internal immutable _stEthAmmPoolsTreasuryManager; - address internal immutable _stEthAmmCharlieTreasury; - address internal immutable _stEthAmmCharlieTreasuryManager; - - address internal immutable _weEth; - uint256 internal immutable _weEthDecimals; - address internal immutable _weEthAmmStorage; - address internal immutable _weEthAmmTreasury; - address internal immutable _weEthAmmPoolsTreasury; - address internal immutable _weEthAmmPoolsTreasuryManager; - address internal immutable _weEthAmmCharlieTreasury; - address internal immutable _weEthAmmCharlieTreasuryManager; - - address internal immutable _usdm; - uint256 internal immutable _usdmDecimals; - address internal immutable _usdmAmmStorage; - address internal immutable _usdmAmmTreasury; - address internal immutable _usdmAmmPoolsTreasury; - address internal immutable _usdmAmmPoolsTreasuryManager; - address internal immutable _usdmAmmCharlieTreasury; - address internal immutable _usdmAmmCharlieTreasuryManager; - - modifier onlySupportedAssetManagement(address asset) { - if (asset == _stEth || asset == _weEth || asset == _usdm) { - revert IporErrors.UnsupportedModule(IporErrors.UNSUPPORTED_MODULE_ASSET_MANAGEMENT, asset); - } - _; - } - - constructor( - AmmGovernancePoolConfiguration memory usdtPoolCfg, - AmmGovernancePoolConfiguration memory usdcPoolCfg, - AmmGovernancePoolConfiguration memory daiPoolCfg, - AmmGovernancePoolConfiguration memory stEthPoolCfg, - AmmGovernancePoolConfiguration memory weEthPoolCfg, - AmmGovernancePoolConfiguration memory usdmPoolCfg - ) { - _usdt = usdtPoolCfg.asset.checkAddress(); - _usdtDecimals = usdtPoolCfg.decimals; - _usdtAmmStorage = usdtPoolCfg.ammStorage.checkAddress(); - _usdtAmmTreasury = usdtPoolCfg.ammTreasury.checkAddress(); - _usdtAmmVault = usdtPoolCfg.ammVault.checkAddress(); - _usdtAmmPoolsTreasury = usdtPoolCfg.ammPoolsTreasury.checkAddress(); - _usdtAmmPoolsTreasuryManager = usdtPoolCfg.ammPoolsTreasuryManager.checkAddress(); - _usdtAmmCharlieTreasury = usdtPoolCfg.ammCharlieTreasury.checkAddress(); - _usdtAmmCharlieTreasuryManager = usdtPoolCfg.ammCharlieTreasuryManager.checkAddress(); - - _usdc = usdcPoolCfg.asset.checkAddress(); - _usdcDecimals = usdcPoolCfg.decimals; - _usdcAmmStorage = usdcPoolCfg.ammStorage.checkAddress(); - _usdcAmmTreasury = usdcPoolCfg.ammTreasury.checkAddress(); - _usdcAmmVault = usdcPoolCfg.ammVault.checkAddress(); - _usdcAmmPoolsTreasury = usdcPoolCfg.ammPoolsTreasury.checkAddress(); - _usdcAmmPoolsTreasuryManager = usdcPoolCfg.ammPoolsTreasuryManager.checkAddress(); - _usdcAmmCharlieTreasury = usdcPoolCfg.ammCharlieTreasury.checkAddress(); - _usdcAmmCharlieTreasuryManager = usdcPoolCfg.ammCharlieTreasuryManager.checkAddress(); - - _dai = daiPoolCfg.asset.checkAddress(); - _daiDecimals = daiPoolCfg.decimals; - _daiAmmStorage = daiPoolCfg.ammStorage.checkAddress(); - _daiAmmTreasury = daiPoolCfg.ammTreasury.checkAddress(); - _daiAmmVault = daiPoolCfg.ammVault.checkAddress(); - _daiAmmPoolsTreasury = daiPoolCfg.ammPoolsTreasury.checkAddress(); - _daiAmmPoolsTreasuryManager = daiPoolCfg.ammPoolsTreasuryManager.checkAddress(); - _daiAmmCharlieTreasury = daiPoolCfg.ammCharlieTreasury.checkAddress(); - _daiAmmCharlieTreasuryManager = daiPoolCfg.ammCharlieTreasuryManager.checkAddress(); - - _stEth = stEthPoolCfg.asset.checkAddress(); - _stEthDecimals = stEthPoolCfg.decimals; - _stEthAmmStorage = stEthPoolCfg.ammStorage.checkAddress(); - _stEthAmmTreasury = stEthPoolCfg.ammTreasury.checkAddress(); - _stEthAmmPoolsTreasury = stEthPoolCfg.ammPoolsTreasury.checkAddress(); - _stEthAmmPoolsTreasuryManager = stEthPoolCfg.ammPoolsTreasuryManager.checkAddress(); - _stEthAmmCharlieTreasury = stEthPoolCfg.ammCharlieTreasury.checkAddress(); - _stEthAmmCharlieTreasuryManager = stEthPoolCfg.ammCharlieTreasuryManager.checkAddress(); - - _weEth = weEthPoolCfg.asset.checkAddress(); - _weEthDecimals = weEthPoolCfg.decimals; - _weEthAmmStorage = weEthPoolCfg.ammStorage.checkAddress(); - _weEthAmmTreasury = weEthPoolCfg.ammTreasury.checkAddress(); - _weEthAmmPoolsTreasury = weEthPoolCfg.ammPoolsTreasury.checkAddress(); - _weEthAmmPoolsTreasuryManager = weEthPoolCfg.ammPoolsTreasuryManager.checkAddress(); - _weEthAmmCharlieTreasury = weEthPoolCfg.ammCharlieTreasury.checkAddress(); - _weEthAmmCharlieTreasuryManager = weEthPoolCfg.ammCharlieTreasuryManager.checkAddress(); - - _usdm = usdmPoolCfg.asset.checkAddress(); - _usdmDecimals = usdmPoolCfg.decimals; - _usdmAmmStorage = usdmPoolCfg.ammStorage.checkAddress(); - _usdmAmmTreasury = usdmPoolCfg.ammTreasury.checkAddress(); - _usdmAmmPoolsTreasury = usdmPoolCfg.ammPoolsTreasury.checkAddress(); - _usdmAmmPoolsTreasuryManager = usdmPoolCfg.ammPoolsTreasuryManager.checkAddress(); - _usdmAmmCharlieTreasury = usdmPoolCfg.ammCharlieTreasury.checkAddress(); - _usdmAmmCharlieTreasuryManager = usdmPoolCfg.ammCharlieTreasuryManager.checkAddress(); - } - - function getAmmGovernancePoolConfiguration( - address asset - ) external view override returns (AmmGovernancePoolConfiguration memory) { - return _getPoolConfiguration(asset); - } - - function depositToAssetManagement( - address asset, - uint256 wadAssetAmount - ) external override onlySupportedAssetManagement(asset) { - IAmmTreasury(_getAmmTreasury(asset)).depositToAssetManagementInternal(wadAssetAmount); - } - - function withdrawFromAssetManagement( - address asset, - uint256 wadAssetAmount - ) external override onlySupportedAssetManagement(asset) { - IAmmTreasury(_getAmmTreasury(asset)).withdrawFromAssetManagementInternal(wadAssetAmount); - } - - function withdrawAllFromAssetManagement(address asset) external override onlySupportedAssetManagement(asset) { - IAmmTreasury(_getAmmTreasury(asset)).withdrawAllFromAssetManagementInternal(); - } - - function transferToTreasury(address asset, uint256 wadAssetAmountInput) external override { - AmmGovernancePoolConfiguration memory poolCfg = _getPoolConfiguration(asset); - - require(msg.sender == poolCfg.ammPoolsTreasuryManager, AmmPoolsErrors.CALLER_NOT_TREASURY_MANAGER); - - uint256 assetAmountAssetDecimals = IporMath.convertWadToAssetDecimals(wadAssetAmountInput, poolCfg.decimals); - uint256 wadAssetAmount = IporMath.convertToWad(assetAmountAssetDecimals, poolCfg.decimals); - - IAmmStorage(poolCfg.ammStorage).updateStorageWhenTransferToTreasuryInternal(wadAssetAmount); - - IERC20Upgradeable(asset).safeTransferFrom( - poolCfg.ammTreasury, - poolCfg.ammPoolsTreasury, - assetAmountAssetDecimals - ); - } - - function transferToCharlieTreasury(address asset, uint256 wadAssetAmountInput) external override { - AmmGovernancePoolConfiguration memory poolCfg = _getPoolConfiguration(asset); - - require(msg.sender == poolCfg.ammCharlieTreasuryManager, AmmPoolsErrors.CALLER_NOT_PUBLICATION_FEE_TRANSFERER); - - uint256 assetAmountAssetDecimals = IporMath.convertWadToAssetDecimals(wadAssetAmountInput, poolCfg.decimals); - uint256 wadAssetAmount = IporMath.convertToWad(assetAmountAssetDecimals, poolCfg.decimals); - - IAmmStorage(poolCfg.ammStorage).updateStorageWhenTransferToCharlieTreasuryInternal(wadAssetAmount); - - IERC20Upgradeable(asset).safeTransferFrom( - poolCfg.ammTreasury, - poolCfg.ammCharlieTreasury, - assetAmountAssetDecimals - ); - } - - function addSwapLiquidator(address asset, address account) external override { - AmmConfigurationManager.addSwapLiquidator(asset, account); - } - - function removeSwapLiquidator(address asset, address account) external override { - AmmConfigurationManager.removeSwapLiquidator(asset, account); - } - - function isSwapLiquidator(address asset, address account) external view override returns (bool) { - return AmmConfigurationManager.isSwapLiquidator(asset, account); - } - - function addAppointedToRebalanceInAmm( - address asset, - address account - ) external override onlySupportedAssetManagement(asset) { - AmmConfigurationManager.addAppointedToRebalanceInAmm(asset, account); - } - - function removeAppointedToRebalanceInAmm( - address asset, - address account - ) external override onlySupportedAssetManagement(asset) { - AmmConfigurationManager.removeAppointedToRebalanceInAmm(asset, account); - } - - function isAppointedToRebalanceInAmm(address asset, address account) external view override returns (bool) { - return AmmConfigurationManager.isAppointedToRebalanceInAmm(asset, account); - } - - function setAmmPoolsParams( - address asset, - uint32 newMaxLiquidityPoolBalance, - uint32 newAutoRebalanceThreshold, - uint16 newAmmTreasuryAndAssetManagementRatio - ) external override { - AmmConfigurationManager.setAmmPoolsParams( - asset, - newMaxLiquidityPoolBalance, - newAutoRebalanceThreshold, - newAmmTreasuryAndAssetManagementRatio - ); - } - - function getAmmPoolsParams(address asset) external view override returns (AmmPoolsParamsConfiguration memory cfg) { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(asset); - cfg = AmmPoolsParamsConfiguration({ - maxLiquidityPoolBalance: uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, - autoRebalanceThreshold: ammPoolsParamsCfg.autoRebalanceThreshold, - ammTreasuryAndAssetManagementRatio: ammPoolsParamsCfg.ammTreasuryAndAssetManagementRatio - }); - } - - function _getPoolConfiguration(address asset) internal view returns (AmmGovernancePoolConfiguration memory) { - if (asset == _usdt) { - return - AmmGovernancePoolConfiguration({ - asset: _usdt, - decimals: _usdtDecimals, - ammStorage: _usdtAmmStorage, - ammTreasury: _usdtAmmTreasury, - ammVault: _usdtAmmVault, - ammPoolsTreasury: _usdtAmmPoolsTreasury, - ammPoolsTreasuryManager: _usdtAmmPoolsTreasuryManager, - ammCharlieTreasury: _usdtAmmCharlieTreasury, - ammCharlieTreasuryManager: _usdtAmmCharlieTreasuryManager - }); - } else if (asset == _usdc) { - return - AmmGovernancePoolConfiguration({ - asset: _usdc, - decimals: _usdcDecimals, - ammStorage: _usdcAmmStorage, - ammTreasury: _usdcAmmTreasury, - ammVault: _usdcAmmVault, - ammPoolsTreasury: _usdcAmmPoolsTreasury, - ammPoolsTreasuryManager: _usdcAmmPoolsTreasuryManager, - ammCharlieTreasury: _usdcAmmCharlieTreasury, - ammCharlieTreasuryManager: _usdcAmmCharlieTreasuryManager - }); - } else if (asset == _dai) { - return - AmmGovernancePoolConfiguration({ - asset: _dai, - decimals: _daiDecimals, - ammStorage: _daiAmmStorage, - ammTreasury: _daiAmmTreasury, - ammVault: _daiAmmVault, - ammPoolsTreasury: _daiAmmPoolsTreasury, - ammPoolsTreasuryManager: _daiAmmPoolsTreasuryManager, - ammCharlieTreasury: _daiAmmCharlieTreasury, - ammCharlieTreasuryManager: _daiAmmCharlieTreasuryManager - }); - } else if (asset == _stEth) { - return - AmmGovernancePoolConfiguration({ - asset: _stEth, - decimals: _stEthDecimals, - ammStorage: _stEthAmmStorage, - ammTreasury: _stEthAmmTreasury, - ammVault: address(0), - ammPoolsTreasury: _stEthAmmPoolsTreasury, - ammPoolsTreasuryManager: _stEthAmmPoolsTreasuryManager, - ammCharlieTreasury: _stEthAmmCharlieTreasury, - ammCharlieTreasuryManager: _stEthAmmCharlieTreasuryManager - }); - } else if (asset == _weEth) { - return - AmmGovernancePoolConfiguration({ - asset: _weEth, - decimals: _weEthDecimals, - ammStorage: _weEthAmmStorage, - ammTreasury: _weEthAmmTreasury, - ammVault: address(0), - ammPoolsTreasury: _weEthAmmPoolsTreasury, - ammPoolsTreasuryManager: _weEthAmmPoolsTreasuryManager, - ammCharlieTreasury: _weEthAmmCharlieTreasury, - ammCharlieTreasuryManager: _weEthAmmCharlieTreasuryManager - }); - } else if (asset == _usdm) { - return - AmmGovernancePoolConfiguration({ - asset: _usdm, - decimals: _usdmDecimals, - ammStorage: _usdmAmmStorage, - ammTreasury: _usdmAmmTreasury, - ammVault: address(0), - ammPoolsTreasury: _usdmAmmPoolsTreasury, - ammPoolsTreasuryManager: _usdmAmmPoolsTreasuryManager, - ammCharlieTreasury: _usdmAmmCharlieTreasury, - ammCharlieTreasuryManager: _usdmAmmCharlieTreasuryManager - }); - } else { - revert(IporErrors.ASSET_NOT_SUPPORTED); - } - } - - function _getAmmTreasury(address asset) internal view returns (address) { - if (asset == _usdt) { - return _usdtAmmTreasury; - } else if (asset == _usdc) { - return _usdcAmmTreasury; - } else if (asset == _dai) { - return _daiAmmTreasury; - } else if (asset == _stEth) { - return _stEthAmmTreasury; - } else if (asset == _weEth) { - return _weEthAmmTreasury; - } else if (asset == _usdm) { - return _usdmAmmTreasury; - } else { - revert(IporErrors.ASSET_NOT_SUPPORTED); - } - } -} diff --git a/contracts/amm-eth/AmmOpenSwapServiceStEth.sol b/contracts/chains/ethereum/amm-stEth/AmmOpenSwapServiceStEth.sol similarity index 90% rename from contracts/amm-eth/AmmOpenSwapServiceStEth.sol rename to contracts/chains/ethereum/amm-stEth/AmmOpenSwapServiceStEth.sol index 362d79e7e..b8b35a6b3 100644 --- a/contracts/amm-eth/AmmOpenSwapServiceStEth.sol +++ b/contracts/chains/ethereum/amm-stEth/AmmOpenSwapServiceStEth.sol @@ -2,12 +2,23 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; -import "../interfaces/IAmmOpenSwapServiceStEth.sol"; -import "./interfaces/IStETH.sol"; -import "./interfaces/IWETH9.sol"; -import "./interfaces/IwstEth.sol"; -import "./interfaces/IAmmPoolsServiceStEth.sol"; -import "../base/amm/services/AmmOpenSwapServiceBaseV1.sol"; +import "../../../interfaces/IAmmOpenSwapServiceStEth.sol"; +import "../../../amm-eth/interfaces/IStETH.sol"; +import "../../../amm-eth/interfaces/IWETH9.sol"; +import "../../../amm-eth/interfaces/IwstEth.sol"; +import "../../../amm-eth/interfaces/IAmmPoolsServiceStEth.sol"; +import {AmmOpenSwapServiceBaseV1} from "../../../base/amm/services/AmmOpenSwapServiceBaseV1.sol"; +import {StorageLibBaseV1} from "../../../base/libraries/StorageLibBaseV1.sol"; + +import {IporContractValidator} from "../../../libraries/IporContractValidator.sol"; + +import {AmmTypes} from "../../../interfaces/types/AmmTypes.sol"; +import {AmmTypesBaseV1} from "../../../base/types/AmmTypesBaseV1.sol"; + +import {IporErrors} from "../../../libraries/errors/IporErrors.sol"; +import {AmmErrors} from "../../../libraries/errors/AmmErrors.sol"; +import {IporTypes} from "../../../interfaces/types/IporTypes.sol"; + /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. /// @dev Service can be safely used directly only if you are sure that methods will not touch any storage variables. @@ -15,7 +26,6 @@ contract AmmOpenSwapServiceStEth is AmmOpenSwapServiceBaseV1, IAmmOpenSwapServic using SafeERC20Upgradeable for IERC20Upgradeable; using IporContractValidator for address; - address public immutable messageSigner; address public immutable wETH; address public immutable wstETH; @@ -30,11 +40,9 @@ contract AmmOpenSwapServiceStEth is AmmOpenSwapServiceBaseV1, IAmmOpenSwapServic constructor( AmmTypesBaseV1.AmmOpenSwapServicePoolConfiguration memory poolCfg, address iporOracleInput, - address messageSignerInput, address wETHInput, address wstETHInput ) AmmOpenSwapServiceBaseV1(poolCfg, iporOracleInput) { - messageSigner = messageSignerInput.checkAddress(); wETH = wETHInput.checkAddress(); wstETH = wstETHInput.checkAddress(); } @@ -160,7 +168,7 @@ contract AmmOpenSwapServiceStEth is AmmOpenSwapServiceBaseV1, IAmmOpenSwapServic } function _getMessageSigner() internal view override returns (address) { - return messageSigner; + return StorageLibBaseV1.getMessageSignerStorage().value; } function _convertToAssetAmount( diff --git a/contracts/chains/ethereum/amm-stEth/AmmPoolsServiceStEth.sol b/contracts/chains/ethereum/amm-stEth/AmmPoolsServiceStEth.sol new file mode 100644 index 000000000..db32ed9c9 --- /dev/null +++ b/contracts/chains/ethereum/amm-stEth/AmmPoolsServiceStEth.sol @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity 0.8.26; + +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "../../../interfaces/IIpToken.sol"; +import "../../../interfaces/types/AmmTypes.sol"; +import "../../../amm-eth/interfaces/IStETH.sol"; +import "../../../amm-eth/interfaces/IWETH9.sol"; +import "../../../amm-eth/interfaces/IAmmPoolsServiceStEth.sol"; +import "../../../libraries/errors/AmmErrors.sol"; +import "../../../libraries/errors/IporErrors.sol"; +import "../../../libraries/math/IporMath.sol"; +import "../../../libraries/IporContractValidator.sol"; +import "../../../libraries/AmmLib.sol"; +import "../../../governance/AmmConfigurationManager.sol"; +import "../../../base/interfaces/IAmmTreasuryBaseV2.sol"; +import "../../../base/amm/services/AmmPoolsServiceBaseV1.sol"; + +/// @title AMM Pools Service for stETH with Asset Management (V2) +/// @notice Supports providing liquidity with stETH, ETH, and WETH +/// @notice Includes auto-rebalancing between AMM Treasury and Asset Management (Plasma Vault) +/// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. +contract AmmPoolsServiceStEth is IAmmPoolsServiceStEth, AmmPoolsServiceBaseV1 { + using IporContractValidator for address; + using SafeERC20 for IStETH; + using SafeERC20 for IWETH9; + using AmmLib for AmmTypes.AmmPoolCoreModel; + + address public immutable stEth; + address public immutable wEth; + + constructor( + address stEth_, + address wEth_, + address ipToken_, + address ammTreasury_, + address ammStorage_, + address ammAssetManagement_, + address iporOracle_, + address iporProtocolRouter_, + uint256 redeemFeeRate_, + uint256 autoRebalanceThresholdMultiplier_ + ) + AmmPoolsServiceBaseV1( + stEth_, + ipToken_, + ammTreasury_, + ammStorage_, + ammAssetManagement_, + iporOracle_, + iporProtocolRouter_, + redeemFeeRate_, + autoRebalanceThresholdMultiplier_ + ) + { + stEth = stEth_.checkAddress(); + wEth = wEth_.checkAddress(); + } + + /// @notice Provides liquidity to the AMM pool using stETH tokens + /// @param beneficiary Address that will receive ipstETH tokens + /// @param stEthAmount Amount of stETH to deposit (in 18 decimals) + function provideLiquidityStEth(address beneficiary, uint256 stEthAmount) external payable override { + _provideLiquidity(beneficiary, stEthAmount); + } + + /// @notice Provides liquidity to the AMM pool using WETH tokens + /// @dev WETH is unwrapped to ETH and then converted to stETH via Lido + /// @param beneficiary Address that will receive ipstETH tokens + /// @param wEthAmount Amount of WETH to deposit (in 18 decimals) + function provideLiquidityWEth(address beneficiary, uint256 wEthAmount) external payable override { + require(wEthAmount > 0, IporErrors.VALUE_NOT_GREATER_THAN_ZERO); + + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + asset + ); + + uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV2(ammTreasury).getLiquidityPoolBalance(); + uint256 newPoolBalance = wEthAmount + actualLiquidityPoolBalance; + + require( + newPoolBalance <= uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, + AmmErrors.LIQUIDITY_POOL_BALANCE_IS_TOO_HIGH + ); + + IWETH9(wEth).safeTransferFrom(msg.sender, iporProtocolRouter, wEthAmount); + IWETH9(wEth).withdraw(wEthAmount); + + _depositEth(wEthAmount, beneficiary, actualLiquidityPoolBalance); + } + + /// @notice Provides liquidity to the AMM pool using ETH + /// @dev ETH is converted to stETH via Lido + /// @param beneficiary Address that will receive ipstETH tokens + /// @param ethAmount Amount of ETH to deposit (in 18 decimals) + function provideLiquidityEth(address beneficiary, uint256 ethAmount) external payable override { + require(ethAmount > 0, IporErrors.VALUE_NOT_GREATER_THAN_ZERO); + require(msg.value > 0, IporErrors.VALUE_NOT_GREATER_THAN_ZERO); + + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + asset + ); + + uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV2(ammTreasury).getLiquidityPoolBalance(); + uint256 newPoolBalance = ethAmount + actualLiquidityPoolBalance; + + require( + newPoolBalance <= uint256(ammPoolsParamsCfg.maxLiquidityPoolBalance) * 1e18, + AmmErrors.LIQUIDITY_POOL_BALANCE_IS_TOO_HIGH + ); + + _depositEth(ethAmount, beneficiary, actualLiquidityPoolBalance); + } + + /// @notice Redeems ipstETH tokens for stETH + /// @param beneficiary Address that will receive stETH tokens + /// @param ipTokenAmount Amount of ipstETH to burn + function redeemFromAmmPoolStEth(address beneficiary, uint256 ipTokenAmount) external override { + _redeem(beneficiary, ipTokenAmount); + } + + /// @notice Rebalances assets between AMM Treasury and Asset Management (Plasma Vault) + /// @dev Can only be called by appointed rebalancer + function rebalanceBetweenAmmTreasuryAndAssetManagementStEth() external override { + _rebalanceBetweenAmmTreasuryAndAssetManagement(); + } + + /// @notice Override to emit legacy stETH-specific ProvideLiquidityStEth event + function _emitProvideLiquidityEvent( + address beneficiary, + uint256 exchangeRate, + uint256 wadAssetAmount, + uint256 ipTokenAmount + ) internal virtual override { + emit IAmmPoolsServiceStEth.ProvideLiquidityStEth( + msg.sender, + beneficiary, + ammTreasury, + exchangeRate, + wadAssetAmount, + ipTokenAmount + ); + } + + /// @notice Override to emit legacy stETH-specific RedeemStEth event + function _emitRedeemEvent( + address beneficiary, + uint256 exchangeRate, + uint256 wadAssetAmount, + uint256 wadAmountToRedeem, + uint256 ipTokenAmount + ) internal virtual override { + emit IAmmPoolsServiceStEth.RedeemStEth( + ammTreasury, + msg.sender, + beneficiary, + exchangeRate, + wadAssetAmount, + wadAmountToRedeem, + ipTokenAmount + ); + } + + /// @notice Internal function to convert ETH to stETH and mint ipstETH + /// @dev Calls Lido's submit() function to convert ETH to stETH + /// @param ethAmount Amount of ETH to convert + /// @param beneficiary Address that will receive ipstETH tokens + /// @param actualLiquidityPoolBalance Current liquidity pool balance (for exchange rate calculation) + function _depositEth(uint256 ethAmount, address beneficiary, uint256 actualLiquidityPoolBalance) private { + try IStETH(stEth).submit{value: ethAmount}(address(0)) { + uint256 stEthAmount = IStETH(stEth).balanceOf(address(this)); + + if (stEthAmount > 0) { + uint256 exchangeRate = _getExchangeRate(actualLiquidityPoolBalance); + + IStETH(stEth).safeTransfer(ammTreasury, stEthAmount); + + uint256 ipTokenAmount = IporMath.division(stEthAmount * 1e18, exchangeRate); + + IIpToken(ipToken).mint(beneficiary, ipTokenAmount); + + emit IAmmPoolsServiceStEth.ProvideLiquidityEth( + msg.sender, + beneficiary, + ammTreasury, + exchangeRate, + ethAmount, + stEthAmount, + ipTokenAmount + ); + } + } catch { + revert IAmmPoolsServiceStEth.StEthSubmitFailed({ + amount: ethAmount, + errorCode: AmmErrors.STETH_SUBMIT_FAILED + }); + } + } +} diff --git a/contracts/amm-weEth/AmmPoolsServiceWeEth.sol b/contracts/chains/ethereum/amm-weEth/AmmPoolsServiceWeEth.sol similarity index 53% rename from contracts/amm-weEth/AmmPoolsServiceWeEth.sol rename to contracts/chains/ethereum/amm-weEth/AmmPoolsServiceWeEth.sol index b85079433..d2a92d4c4 100644 --- a/contracts/amm-weEth/AmmPoolsServiceWeEth.sol +++ b/contracts/chains/ethereum/amm-weEth/AmmPoolsServiceWeEth.sol @@ -1,25 +1,31 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.26; + import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "../interfaces/IIpToken.sol"; -import "../interfaces/types/AmmTypes.sol"; -import "../libraries/errors/AmmErrors.sol"; -import "../libraries/math/IporMath.sol"; -import "../libraries/StorageLib.sol"; -import "../libraries/IporContractValidator.sol"; -import "../libraries/AmmLib.sol"; -import "../libraries/ProvideLiquidityEvents.sol"; -import "../governance/AmmConfigurationManager.sol"; -import "../base/interfaces/IAmmTreasuryBaseV1.sol"; -import {IAmmPoolsServiceWeEth} from "./interfaces/IAmmPoolsServiceWeEth.sol"; -import {IWeEth} from "./interfaces/IWeEth.sol"; -import {IWETH} from "./interfaces/IWETH.sol"; -import {IEEthLiquidityPool} from "./interfaces/IEEthLiquidityPool.sol"; - +import "../../../interfaces/IIpToken.sol"; +import "../../../interfaces/types/AmmTypes.sol"; +import "../../../libraries/errors/AmmErrors.sol"; +import "../../../libraries/errors/IporErrors.sol"; +import "../../../libraries/math/IporMath.sol"; +import "../../../libraries/IporContractValidator.sol"; +import "../../../libraries/AmmLib.sol"; +import "../../../libraries/ProvideLiquidityEvents.sol"; +import "../../../governance/AmmConfigurationManager.sol"; +import "../../../base/interfaces/IAmmTreasuryBaseV2.sol"; +import "../../../base/amm-weEth/services/AmmPoolsServiceWeEthBaseV1.sol"; +import "../../../amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol"; +import "../../../amm-weEth/interfaces/IWeEth.sol"; +import "../../../amm-weEth/interfaces/IWETH.sol"; +import "../../../amm-weEth/interfaces/IEEthLiquidityPool.sol"; +import "../../../base/libraries/StorageLibBaseV1.sol"; + +/// @title AMM Pools Service for weETH with Asset Management support +/// @notice Supports providing liquidity with weETH, eETH, ETH, and WETH +/// @notice Includes auto-rebalancing between AMM Treasury and Asset Management (Plasma Vault) /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. -contract AmmPoolsServiceWeEth is IAmmPoolsServiceWeEth { +contract AmmPoolsServiceWeEth is IAmmPoolsServiceWeEth, AmmPoolsServiceWeEthBaseV1 { using IporContractValidator for address; using SafeERC20 for IERC20; using SafeERC20 for IWETH; @@ -29,14 +35,8 @@ contract AmmPoolsServiceWeEth is IAmmPoolsServiceWeEth { address public immutable wEth; address public immutable eEth; address public immutable weEth; - address public immutable ipWeEth; - address public immutable eEthLiquidityPoolExternal; // NOT IporPool address from mainnet 0x308861A430be4cce5502d0A12724771Fc6DaF216 - address public immutable ammTreasuryWeEth; - address public immutable ammStorageWeEth; - address public immutable iporOracle; - address public immutable iporProtocolRouter; - uint256 public immutable redeemFeeRateWeEth; - address public immutable referral; // 0x558c8eb91F6fd83FC5C995572c3515E2DAF7b7e0 ??? + address public immutable eEthLiquidityPoolExternal; // ether.fi liquidity pool address from mainnet 0x308861A430be4cce5502d0A12724771Fc6DaF216 + address public immutable referral; struct DeployedContracts { address ethInput; @@ -46,30 +46,44 @@ contract AmmPoolsServiceWeEth is IAmmPoolsServiceWeEth { address ipWeEthInput; address ammTreasuryWeEthInput; address ammStorageWeEthInput; + address ammAssetManagementInput; address iporOracleInput; address iporProtocolRouterInput; uint256 redeemFeeRateWeEthInput; address eEthLiquidityPoolExternalInput; address referralInput; + uint256 autoRebalanceThresholdMultiplierInput; } - constructor(DeployedContracts memory deployedContracts) { + constructor( + DeployedContracts memory deployedContracts + ) + AmmPoolsServiceWeEthBaseV1( + deployedContracts.weEthInput, + deployedContracts.ipWeEthInput, + deployedContracts.ammTreasuryWeEthInput, + deployedContracts.ammStorageWeEthInput, + deployedContracts.ammAssetManagementInput, + deployedContracts.iporOracleInput, + deployedContracts.iporProtocolRouterInput, + deployedContracts.redeemFeeRateWeEthInput, + deployedContracts.autoRebalanceThresholdMultiplierInput + ) + { eth = deployedContracts.ethInput.checkAddress(); wEth = deployedContracts.wEthInput.checkAddress(); eEth = deployedContracts.eEthInput.checkAddress(); weEth = deployedContracts.weEthInput.checkAddress(); - ipWeEth = deployedContracts.ipWeEthInput.checkAddress(); - ammTreasuryWeEth = deployedContracts.ammTreasuryWeEthInput.checkAddress(); - ammStorageWeEth = deployedContracts.ammStorageWeEthInput.checkAddress(); - iporOracle = deployedContracts.iporOracleInput.checkAddress(); - iporProtocolRouter = deployedContracts.iporProtocolRouterInput.checkAddress(); eEthLiquidityPoolExternal = deployedContracts.eEthLiquidityPoolExternalInput.checkAddress(); - redeemFeeRateWeEth = deployedContracts.redeemFeeRateWeEthInput; referral = deployedContracts.referralInput.checkAddress(); - - require(redeemFeeRateWeEth <= 1e18, AmmPoolsErrors.CFG_INVALID_REDEEM_FEE_RATE); } + /// @notice Provides liquidity with various input assets (weETH, eETH, ETH, WETH) + /// @param poolAsset The pool asset (must be weETH) + /// @param inputAsset The input asset (weETH, eETH, ETH, or WETH) + /// @param beneficiary Address that will receive ipweETH tokens + /// @param inputAssetAmount Amount of input asset to deposit + /// @return ipTokenAmount Amount of ipweETH tokens minted function provideLiquidity( address poolAsset, address inputAsset, @@ -108,48 +122,42 @@ contract AmmPoolsServiceWeEth is IAmmPoolsServiceWeEth { revert IporErrors.UnsupportedAssetPair(IporErrors.ASSET_NOT_SUPPORTED, poolAsset, inputAsset); } + /// @notice Provides liquidity directly with weETH + /// @param beneficiary Address that will receive ipweETH tokens + /// @param weEthAmount Amount of weETH to deposit function provideLiquidityWeEthToAmmPoolWeEth(address beneficiary, uint256 weEthAmount) external override { _provideLiquidityWeEthToAmmPoolWeEth(beneficiary, weEthAmount, msg.sender); } - function redeemFromAmmPoolWeEth(address beneficiary, uint256 ipTokenAmount) external { - require( - ipTokenAmount > 0 && ipTokenAmount <= IIpToken(ipWeEth).balanceOf(msg.sender), - AmmPoolsErrors.CANNOT_REDEEM_IP_TOKEN_TOO_LOW - ); - require(beneficiary != address(0), IporErrors.WRONG_ADDRESS); - - uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryWeEth).getLiquidityPoolBalance(); - - uint256 exchangeRate = _getExchangeRate(actualLiquidityPoolBalance); - - uint256 weEthAmount = IporMath.division(ipTokenAmount * exchangeRate, 1e18); - - uint256 amountToRedeem = IporMath.division(weEthAmount * (1e18 - redeemFeeRateWeEth), 1e18); - - require(amountToRedeem > 0, AmmPoolsErrors.CANNOT_REDEEM_ASSET_AMOUNT_TOO_LOW); - - IIpToken(ipWeEth).burn(msg.sender, ipTokenAmount); - - IERC20(weEth).safeTransferFrom(ammTreasuryWeEth, beneficiary, amountToRedeem); + /// @notice Redeems ipweETH tokens for weETH + /// @param beneficiary Address that will receive weETH tokens + /// @param ipTokenAmount Amount of ipweETH tokens to redeem + function redeemFromAmmPoolWeEth( + address beneficiary, + uint256 ipTokenAmount + ) external override(IAmmPoolsServiceWeEth, AmmPoolsServiceWeEthBaseV1) { + _redeem(beneficiary, ipTokenAmount); + } - emit ProvideLiquidityEvents.Redeem( - weEth, - ammTreasuryWeEth, - msg.sender, - beneficiary, - exchangeRate, - weEthAmount, - amountToRedeem, - ipTokenAmount - ); + /// @notice Rebalances assets between AMM Treasury and Asset Management (Plasma Vault) + /// @dev Can only be called by addresses appointed to rebalance + function rebalanceBetweenAmmTreasuryAndAssetManagementWeEth() + external + override(IAmmPoolsServiceWeEth, AmmPoolsServiceWeEthBaseV1) + { + _rebalanceBetweenAmmTreasuryAndAssetManagement(); } + /// @notice Internal function to unwrap WETH to ETH + /// @param wEthAmount Amount of WETH to unwrap function _unwrapWethToEth(uint256 wEthAmount) internal { IWETH(wEth).safeTransferFrom(msg.sender, iporProtocolRouter, wEthAmount); IWETH(wEth).withdraw(wEthAmount); } + /// @notice Internal function to deposit ETH to ether.fi liquidity pool and receive eETH + /// @param ethAmount Amount of ETH to deposit + /// @return eEthAmount Amount of eETH received function _depositEthToEethLiquidityPoolExternal(uint256 ethAmount) internal returns (uint256 eEthAmount) { IEEthLiquidityPool(eEthLiquidityPoolExternal).deposit{value: ethAmount}(referral); eEthAmount = IEEthLiquidityPool(eEthLiquidityPoolExternal).getTotalEtherClaimOf(iporProtocolRouter); @@ -158,6 +166,10 @@ contract AmmPoolsServiceWeEth is IAmmPoolsServiceWeEth { } } + /// @notice Internal function to wrap eETH to weETH + /// @param inputAssetAmount Amount of eETH to wrap + /// @param eEthFrom Address from which to transfer eETH + /// @return weEthAmount Amount of weETH received function _wrapEethToWeEth(uint256 inputAssetAmount, address eEthFrom) internal returns (uint256 weEthAmount) { if (eEthFrom != iporProtocolRouter) { IERC20(eEth).safeTransferFrom(eEthFrom, iporProtocolRouter, inputAssetAmount); @@ -170,14 +182,21 @@ contract AmmPoolsServiceWeEth is IAmmPoolsServiceWeEth { } } + /// @notice Internal function to provide weETH liquidity to the AMM pool + /// @param beneficiary Address that will receive ipweETH tokens + /// @param weEthAmount Amount of weETH to deposit + /// @param weEthFrom Address from which to transfer weETH + /// @return ipTokenAmount Amount of ipweETH tokens minted function _provideLiquidityWeEthToAmmPoolWeEth( address beneficiary, uint256 weEthAmount, address weEthFrom ) internal returns (uint256 ipTokenAmount) { - StorageLib.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams(weEth); + StorageLibBaseV1.AmmPoolsParamsValue memory ammPoolsParamsCfg = AmmConfigurationManager.getAmmPoolsParams( + weEth + ); - uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV1(ammTreasuryWeEth).getLiquidityPoolBalance(); + uint256 actualLiquidityPoolBalance = IAmmTreasuryBaseV2(ammTreasury).getLiquidityPoolBalance(); uint256 newPoolBalance = actualLiquidityPoolBalance + weEthAmount; require( @@ -188,35 +207,26 @@ contract AmmPoolsServiceWeEth is IAmmPoolsServiceWeEth { uint256 exchangeRate = _getExchangeRate(actualLiquidityPoolBalance); if (weEthFrom != iporProtocolRouter) { - IERC20(weEth).safeTransferFrom(weEthFrom, ammTreasuryWeEth, weEthAmount); + IERC20(weEth).safeTransferFrom(weEthFrom, ammTreasury, weEthAmount); } else { - IERC20(weEth).safeTransfer(ammTreasuryWeEth, weEthAmount); + IERC20(weEth).safeTransfer(ammTreasury, weEthAmount); } + ipTokenAmount = IporMath.division(weEthAmount * 1e18, exchangeRate); - IIpToken(ipWeEth).mint(beneficiary, ipTokenAmount); + IIpToken(ipToken).mint(beneficiary, ipTokenAmount); + + /// @dev Order of the following two functions is important, first asset transfer, then rebalance. + _rebalanceIfNeededAfterProvideLiquidity(ammPoolsParamsCfg, weEthAmount); emit ProvideLiquidityEvents.ProvideLiquidity( weEth, msg.sender, beneficiary, - ammTreasuryWeEth, + ammTreasury, exchangeRate, weEthAmount, ipTokenAmount ); } - - function _getExchangeRate(uint256 actualLiquidityPoolBalance) internal view returns (uint256) { - AmmTypes.AmmPoolCoreModel memory model = AmmTypes.AmmPoolCoreModel({ - asset: weEth, - assetDecimals: 18, - ipToken: ipWeEth, - ammStorage: ammStorageWeEth, - ammTreasury: ammTreasuryWeEth, - assetManagement: address(0), - iporOracle: iporOracle - }); - return model.getExchangeRate(actualLiquidityPoolBalance); - } } diff --git a/contracts/chains/ethereum/router/IporProtocolRouter.sol b/contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol similarity index 82% rename from contracts/chains/ethereum/router/IporProtocolRouter.sol rename to contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol index 9ab9dc67a..a21338563 100644 --- a/contracts/chains/ethereum/router/IporProtocolRouter.sol +++ b/contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol @@ -21,51 +21,54 @@ import "../../../interfaces/IPowerTokenFlowsService.sol"; import "../../../interfaces/IPowerTokenStakeService.sol"; import "../../../amm-eth/interfaces/IAmmPoolsServiceStEth.sol"; import "../../../amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol"; -import "../../../amm-eth/interfaces/IAmmPoolsLensStEth.sol"; -import "../../../amm-weEth/interfaces/IAmmPoolsLensWeEth.sol"; import "../../../libraries/errors/IporErrors.sol"; import "../../../libraries/IporContractValidator.sol"; import "../../../router/IporProtocolRouterAbstract.sol"; import "../../../amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol"; -import "../../../amm-usdm/interfaces/IAmmPoolsLensUsdm.sol"; +import "../../../base/interfaces/IAmmGovernanceServiceBaseV1.sol"; -/// @title Entry point for IPOR protocol -contract IporProtocolRouter is IporProtocolRouterAbstract { +import "../../../base/libraries/StorageLibBaseV1.sol"; + +/// @title Entry point for IPOR protocol on Ethereum chain +contract IporProtocolRouterEthereum is IporProtocolRouterAbstract { using IporContractValidator for address; address public immutable ammSwapsLens; + /// @dev for USDT, USDC, DAI pools address public immutable ammPoolsLens; - address public immutable assetManagementLens; - address public immutable ammOpenSwapService; - address public immutable ammOpenSwapServiceStEth; - address public immutable ammCloseSwapServiceUsdt; - address public immutable ammCloseSwapServiceUsdc; - address public immutable ammCloseSwapServiceDai; - address public immutable ammCloseSwapServiceStEth; + /// @dev USDM, weETH, stETH pools + address public immutable ammPoolsLensBaseV1; address public immutable ammCloseSwapLens; - address public immutable ammPoolsService; address public immutable ammGovernanceService; - address public immutable liquidityMiningLens; - address public immutable powerTokenLens; + address public immutable flowService; address public immutable stakeService; - address public immutable ammPoolsServiceStEth; - address public immutable ammPoolsLensStEth; - address public immutable ammPoolsServiceWeEth; - address public immutable ammPoolsLensWeEth; - address public immutable ammPoolsServiceUsdm; - address public immutable ammPoolsLensUsdm; + address public immutable powerTokenLens; + address public immutable liquidityMiningLens; + + address public immutable ammCloseSwapServiceUsdt; + address public immutable ammCloseSwapServiceUsdc; + address public immutable ammCloseSwapServiceDai; + /// @dev for USDT, USDC, DAI pools + address public immutable ammOpenSwapService; + /// @dev for USDT, USDC, DAI pools + address public immutable ammPoolsService; + /// @dev for USDT, USDC, DAI pools + address public immutable assetManagementLens; + + address public immutable stEth; + address public immutable weEth; + address public immutable usdm; struct DeployedContracts { address ammSwapsLens; address ammPoolsLens; + address ammPoolsLensBaseV1; address assetManagementLens; address ammOpenSwapService; - address ammOpenSwapServiceStEth; address ammCloseSwapServiceUsdt; address ammCloseSwapServiceUsdc; address ammCloseSwapServiceDai; - address ammCloseSwapServiceStEth; address ammCloseSwapLens; address ammPoolsService; address ammGovernanceService; @@ -73,37 +76,34 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { address powerTokenLens; address flowService; address stakeService; - address ammPoolsServiceStEth; - address ammPoolsLensStEth; - address ammPoolsServiceWeEth; - address ammPoolsLensWeEth; - address ammPoolsServiceUsdm; - address ammPoolsLensUsdm; + address stEth; + address weEth; + address usdm; } constructor(DeployedContracts memory deployedContracts) { ammSwapsLens = deployedContracts.ammSwapsLens.checkAddress(); ammPoolsLens = deployedContracts.ammPoolsLens.checkAddress(); - assetManagementLens = deployedContracts.assetManagementLens.checkAddress(); - ammOpenSwapService = deployedContracts.ammOpenSwapService.checkAddress(); - ammOpenSwapServiceStEth = deployedContracts.ammOpenSwapServiceStEth.checkAddress(); - ammCloseSwapServiceUsdt = deployedContracts.ammCloseSwapServiceUsdt.checkAddress(); - ammCloseSwapServiceUsdc = deployedContracts.ammCloseSwapServiceUsdc.checkAddress(); - ammCloseSwapServiceDai = deployedContracts.ammCloseSwapServiceDai.checkAddress(); - ammCloseSwapServiceStEth = deployedContracts.ammCloseSwapServiceStEth.checkAddress(); + ammPoolsLensBaseV1 = deployedContracts.ammPoolsLensBaseV1.checkAddress(); ammCloseSwapLens = deployedContracts.ammCloseSwapLens.checkAddress(); - ammPoolsService = deployedContracts.ammPoolsService.checkAddress(); ammGovernanceService = deployedContracts.ammGovernanceService.checkAddress(); - liquidityMiningLens = deployedContracts.liquidityMiningLens.checkAddress(); - powerTokenLens = deployedContracts.powerTokenLens.checkAddress(); + flowService = deployedContracts.flowService.checkAddress(); stakeService = deployedContracts.stakeService.checkAddress(); - ammPoolsServiceStEth = deployedContracts.ammPoolsServiceStEth.checkAddress(); - ammPoolsLensStEth = deployedContracts.ammPoolsLensStEth.checkAddress(); - ammPoolsServiceWeEth = deployedContracts.ammPoolsServiceWeEth.checkAddress(); - ammPoolsLensWeEth = deployedContracts.ammPoolsLensWeEth.checkAddress(); - ammPoolsServiceUsdm = deployedContracts.ammPoolsServiceUsdm.checkAddress(); - ammPoolsLensUsdm = deployedContracts.ammPoolsLensUsdm.checkAddress(); + powerTokenLens = deployedContracts.powerTokenLens.checkAddress(); + liquidityMiningLens = deployedContracts.liquidityMiningLens.checkAddress(); + + ammCloseSwapServiceUsdt = deployedContracts.ammCloseSwapServiceUsdt.checkAddress(); + ammCloseSwapServiceUsdc = deployedContracts.ammCloseSwapServiceUsdc.checkAddress(); + ammCloseSwapServiceDai = deployedContracts.ammCloseSwapServiceDai.checkAddress(); + ammOpenSwapService = deployedContracts.ammOpenSwapService.checkAddress(); + + ammPoolsService = deployedContracts.ammPoolsService.checkAddress(); + assetManagementLens = deployedContracts.assetManagementLens.checkAddress(); + + stEth = deployedContracts.stEth.checkAddress(); + weEth = deployedContracts.weEth.checkAddress(); + usdm = deployedContracts.usdm.checkAddress(); _disableInitializers(); } @@ -115,26 +115,22 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { DeployedContracts({ ammSwapsLens: ammSwapsLens, ammPoolsLens: ammPoolsLens, - assetManagementLens: assetManagementLens, - ammOpenSwapService: ammOpenSwapService, - ammOpenSwapServiceStEth: ammOpenSwapServiceStEth, - ammCloseSwapServiceUsdt: ammCloseSwapServiceUsdt, - ammCloseSwapServiceUsdc: ammCloseSwapServiceUsdc, - ammCloseSwapServiceDai: ammCloseSwapServiceDai, + ammPoolsLensBaseV1: ammPoolsLensBaseV1, ammCloseSwapLens: ammCloseSwapLens, - ammCloseSwapServiceStEth: ammCloseSwapServiceStEth, - ammPoolsService: ammPoolsService, ammGovernanceService: ammGovernanceService, - liquidityMiningLens: liquidityMiningLens, - powerTokenLens: powerTokenLens, flowService: flowService, stakeService: stakeService, - ammPoolsServiceStEth: ammPoolsServiceStEth, - ammPoolsLensStEth: ammPoolsLensStEth, - ammPoolsServiceWeEth: ammPoolsServiceWeEth, - ammPoolsLensWeEth: ammPoolsLensWeEth, - ammPoolsServiceUsdm: ammPoolsServiceUsdm, - ammPoolsLensUsdm: ammPoolsLensUsdm + powerTokenLens: powerTokenLens, + liquidityMiningLens: liquidityMiningLens, + ammCloseSwapServiceUsdt: ammCloseSwapServiceUsdt, + ammCloseSwapServiceUsdc: ammCloseSwapServiceUsdc, + ammCloseSwapServiceDai: ammCloseSwapServiceDai, + ammOpenSwapService: ammOpenSwapService, + ammPoolsService: ammPoolsService, + assetManagementLens: assetManagementLens, + stEth: stEth, + weEth: weEth, + usdm: usdm }); } @@ -150,7 +146,10 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { if (batchOperation == 0) { _nonReentrantBefore(); } - return ammOpenSwapServiceStEth; + StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + stEth + ]; + return servicesCfg.ammOpenSwapService; } else if ( _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed60daysUsdt.selector) || _checkFunctionSigAndIsNotPause(sig, IAmmOpenSwapService.openSwapPayFixed28daysUsdt.selector) || @@ -179,7 +178,10 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { if (batchOperation == 0) { _nonReentrantBefore(); } - return ammCloseSwapServiceStEth; + StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + stEth + ]; + return servicesCfg.ammCloseSwapService; } else if (_checkFunctionSigAndIsNotPause(sig, IAmmCloseSwapServiceUsdt.closeSwapsUsdt.selector)) { if (batchOperation == 0) { _nonReentrantBefore(); @@ -199,21 +201,35 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.provideLiquidityStEth.selector) || _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.provideLiquidityWEth.selector) || _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.provideLiquidityEth.selector) || - _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.redeemFromAmmPoolStEth.selector) + _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceStEth.redeemFromAmmPoolStEth.selector) || + _checkFunctionSigAndIsNotPause( + sig, + IAmmPoolsServiceStEth.rebalanceBetweenAmmTreasuryAndAssetManagementStEth.selector + ) ) { if (batchOperation == 0) { _nonReentrantBefore(); } - return ammPoolsServiceStEth; + StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + stEth + ]; + return servicesCfg.ammPoolsService; } else if ( _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWeEth.provideLiquidityWeEthToAmmPoolWeEth.selector) || _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWeEth.provideLiquidity.selector) || - _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWeEth.redeemFromAmmPoolWeEth.selector) + _checkFunctionSigAndIsNotPause(sig, IAmmPoolsServiceWeEth.redeemFromAmmPoolWeEth.selector) || + _checkFunctionSigAndIsNotPause( + sig, + IAmmPoolsServiceWeEth.rebalanceBetweenAmmTreasuryAndAssetManagementWeEth.selector + ) ) { if (batchOperation == 0) { _nonReentrantBefore(); } - return ammPoolsServiceWeEth; + StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + weEth + ]; + return servicesCfg.ammPoolsService; } else if ( _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.provideLiquidityUsdt.selector) || _checkFunctionSigAndIsNotPause(sig, IAmmPoolsService.provideLiquidityUsdc.selector) || @@ -234,7 +250,10 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { if (batchOperation == 0) { _nonReentrantBefore(); } - return ammPoolsServiceUsdm; + StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + usdm + ]; + return servicesCfg.ammPoolsService; } else if ( _checkFunctionSigAndIsNotPause(sig, IPowerTokenStakeService.stakeLpTokensToLiquidityMining.selector) || _checkFunctionSigAndIsNotPause(sig, IPowerTokenStakeService.unstakeLpTokensFromLiquidityMining.selector) || @@ -284,13 +303,20 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { sig == IAmmGovernanceService.depositToAssetManagement.selector || sig == IAmmGovernanceService.withdrawFromAssetManagement.selector || sig == IAmmGovernanceService.withdrawAllFromAssetManagement.selector || - sig == IAmmGovernanceService.setAmmPoolsParams.selector + sig == IAmmGovernanceService.setAmmPoolsParams.selector || + sig == IAmmGovernanceServiceBaseV1.setMessageSigner.selector || + sig == IAmmGovernanceServiceBaseV1.setAssetLensData.selector || + sig == IAmmGovernanceServiceBaseV1.setAmmGovernancePoolConfiguration.selector || + sig == IAmmGovernanceServiceBaseV1.setAssetServices.selector ) { _onlyOwner(); return ammGovernanceService; } else if (sig == IAmmCloseSwapServiceStEth.emergencyCloseSwapsStEth.selector) { _onlyOwner(); - return ammCloseSwapServiceStEth; + StorageLibBaseV1.AssetServicesValue storage servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + stEth + ]; + return servicesCfg.ammCloseSwapService; } else if (sig == IAmmCloseSwapServiceUsdt.emergencyCloseSwapsUsdt.selector) { _onlyOwner(); return ammCloseSwapServiceUsdt; @@ -320,11 +346,23 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { ) { return ammSwapsLens; } else if ( - sig == IAmmPoolsLens.getAmmPoolsLensConfiguration.selector || - sig == IAmmPoolsLens.getIpTokenExchangeRate.selector || - sig == IAmmPoolsLens.getAmmBalance.selector + sig == IAmmPoolsLens.getAmmPoolsLensConfiguration.selector || sig == IAmmPoolsLens.getAmmBalance.selector ) { return ammPoolsLens; + } else if (sig == IAmmPoolsLens.getIpTokenExchangeRate.selector) { + // Extract asset address from calldata (first parameter after selector) + address asset; + assembly { + asset := calldataload(4) + } + + // Check if asset uses new BaseV1 architecture (stETH, weETH, USDM) + if (asset == stEth || asset == weEth || asset == usdm) { + return ammPoolsLensBaseV1; + } else { + // For legacy assets (USDT, USDC, DAI) + return ammPoolsLens; + } } else if ( sig == IAssetManagementLens.balanceOfAmmTreasuryInAssetManagement.selector || sig == IAssetManagementLens.getAssetManagementConfiguration.selector @@ -355,12 +393,6 @@ contract IporProtocolRouter is IporProtocolRouterAbstract { sig == IAmmCloseSwapLens.getClosingSwapDetails.selector ) { return ammCloseSwapLens; - } else if (sig == IAmmPoolsLensStEth.getIpstEthExchangeRate.selector) { - return ammPoolsLensStEth; - } else if (sig == IAmmPoolsLensWeEth.getIpWeEthExchangeRate.selector) { - return ammPoolsLensWeEth; - } else if (sig == IAmmPoolsLensUsdm.getIpUsdmExchangeRate.selector) { - return ammPoolsLensUsdm; } else if (sig == IAmmPoolsService.getAmmPoolServiceConfiguration.selector) { return ammPoolsService; } diff --git a/contracts/governance/AmmConfigurationManager.sol b/contracts/governance/AmmConfigurationManager.sol index 45c72b9b8..0d0f4402d 100644 --- a/contracts/governance/AmmConfigurationManager.sol +++ b/contracts/governance/AmmConfigurationManager.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; import "../libraries/errors/IporErrors.sol"; import "../libraries/errors/AmmPoolsErrors.sol"; -import "../libraries/StorageLib.sol"; +import "../base/libraries/StorageLibBaseV1.sol"; /// @title Configuration manager for AMM library AmmConfigurationManager { @@ -39,7 +39,7 @@ library AmmConfigurationManager { require(account != address(0), IporErrors.WRONG_ADDRESS); require(asset != address(0), IporErrors.WRONG_ADDRESS); - mapping(address => mapping(address => bool)) storage swapLiquidators = StorageLib + mapping(address => mapping(address => bool)) storage swapLiquidators = StorageLibBaseV1 .getAmmSwapsLiquidatorsStorage() .value; swapLiquidators[asset][account] = true; @@ -55,7 +55,7 @@ library AmmConfigurationManager { require(account != address(0), IporErrors.WRONG_ADDRESS); require(asset != address(0), IporErrors.WRONG_ADDRESS); - mapping(address => mapping(address => bool)) storage swapLiquidators = StorageLib + mapping(address => mapping(address => bool)) storage swapLiquidators = StorageLibBaseV1 .getAmmSwapsLiquidatorsStorage() .value; swapLiquidators[asset][account] = false; @@ -68,7 +68,7 @@ library AmmConfigurationManager { /// @param account address of the account /// @return true if account is a SwapLiquidator, false otherwise function isSwapLiquidator(address asset, address account) internal view returns (bool) { - mapping(address => mapping(address => bool)) storage swapLiquidators = StorageLib + mapping(address => mapping(address => bool)) storage swapLiquidators = StorageLibBaseV1 .getAmmSwapsLiquidatorsStorage() .value; return swapLiquidators[asset][account]; @@ -82,7 +82,7 @@ library AmmConfigurationManager { require(asset != address(0), IporErrors.WRONG_ADDRESS); require(account != address(0), IporErrors.WRONG_ADDRESS); - mapping(address => mapping(address => bool)) storage appointedToRebalance = StorageLib + mapping(address => mapping(address => bool)) storage appointedToRebalance = StorageLibBaseV1 .getAmmPoolsAppointedToRebalanceStorage() .value; appointedToRebalance[asset][account] = true; @@ -98,7 +98,7 @@ library AmmConfigurationManager { require(asset != address(0), IporErrors.WRONG_ADDRESS); require(account != address(0), IporErrors.WRONG_ADDRESS); - mapping(address => mapping(address => bool)) storage appointedToRebalance = StorageLib + mapping(address => mapping(address => bool)) storage appointedToRebalance = StorageLibBaseV1 .getAmmPoolsAppointedToRebalanceStorage() .value; appointedToRebalance[asset][account] = false; @@ -111,7 +111,7 @@ library AmmConfigurationManager { /// @param account address of the account /// @return true if account is appointed to rebalance, false otherwise function isAppointedToRebalanceInAmm(address asset, address account) internal view returns (bool) { - mapping(address => mapping(address => bool)) storage appointedToRebalance = StorageLib + mapping(address => mapping(address => bool)) storage appointedToRebalance = StorageLibBaseV1 .getAmmPoolsAppointedToRebalanceStorage() .value; return appointedToRebalance[asset][account]; @@ -130,11 +130,11 @@ library AmmConfigurationManager { uint16 newAmmTreasuryAndAssetManagementRatio ) internal { require(asset != address(0), IporErrors.WRONG_ADDRESS); - /// @dev newAmmTreasuryAndAssetManagementRatio is percentage with 2 decimals, example: 65% = 6500, (see description in StorageLib.AmmPoolsParamsValue) + /// @dev newAmmTreasuryAndAssetManagementRatio is percentage with 2 decimals, example: 65% = 6500, (see description in StorageLibBaseV1.AmmPoolsParamsValue) /// value cannot be greater than 10000 which is 100% require(newAmmTreasuryAndAssetManagementRatio < 1e4, AmmPoolsErrors.AMM_TREASURY_ASSET_MANAGEMENT_RATIO); - StorageLib.getAmmPoolsParamsStorage().value[asset] = StorageLib.AmmPoolsParamsValue({ + StorageLibBaseV1.getAmmPoolsParamsStorage().value[asset] = StorageLibBaseV1.AmmPoolsParamsValue({ maxLiquidityPoolBalance: newMaxLiquidityPoolBalance, autoRebalanceThreshold: newAutoRebalanceThreshold, ammTreasuryAndAssetManagementRatio: newAmmTreasuryAndAssetManagementRatio @@ -151,7 +151,7 @@ library AmmConfigurationManager { /// @notice Gets AMM Pools Params. /// @param asset address of the asset (pool) /// @return AMM Pools Params struct - function getAmmPoolsParams(address asset) internal view returns (StorageLib.AmmPoolsParamsValue memory) { - return StorageLib.getAmmPoolsParamsStorage().value[asset]; + function getAmmPoolsParams(address asset) internal view returns (StorageLibBaseV1.AmmPoolsParamsValue memory) { + return StorageLibBaseV1.getAmmPoolsParamsStorage().value[asset]; } } diff --git a/contracts/interfaces/IIporProtocol.sol b/contracts/interfaces/IIporProtocol.sol index 25c5d4afb..03cfbea4a 100644 --- a/contracts/interfaces/IIporProtocol.sol +++ b/contracts/interfaces/IIporProtocol.sol @@ -22,11 +22,8 @@ import "./IAmmGovernanceLens.sol"; import "./IPowerTokenStakeService.sol"; import "./IPowerTokenFlowsService.sol"; import "./ISwapEventsBaseV1.sol"; -import "../amm-eth/interfaces/IAmmPoolsLensStEth.sol"; import "../amm-eth/interfaces/IAmmPoolsServiceStEth.sol"; import "../amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol"; -import "../amm-weEth/interfaces/IAmmPoolsLensWeEth.sol"; -import "../amm-usdm/interfaces/IAmmPoolsLensUsdm.sol"; import "../amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol"; import "./IAmmOpenSwapServiceStEth.sol"; import "./IProvideLiquidityEvents.sol"; @@ -43,8 +40,6 @@ interface IIporProtocol is IAssetManagementLens, ILiquidityMiningLens, IPowerTokenLens, - IAmmPoolsLensStEth, - IAmmPoolsLensWeEth, IAmmOpenSwapService, IAmmOpenSwapServiceStEth, IAmmCloseSwapServiceUsdt, @@ -61,7 +56,6 @@ interface IIporProtocol is IAmmPoolsServiceStEth, ISwapEventsBaseV1, IAmmPoolsServiceUsdm, - IAmmPoolsLensUsdm, IProvideLiquidityEvents { diff --git a/contracts/libraries/StorageLib.sol b/contracts/libraries/StorageLib.sol deleted file mode 100644 index cbaab8581..000000000 --- a/contracts/libraries/StorageLib.sol +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.26; - -/// @title Storage ID's associated with the IPOR Protocol Router. -library StorageLib { - uint256 constant STORAGE_SLOT_BASE = 1_000_000; - - // append only - enum StorageId { - /// @dev The address of the contract owner. - Owner, - AppointedOwner, - Paused, - PauseGuardian, - ReentrancyStatus, - RouterFunctionPaused, - AmmSwapsLiquidators, - AmmPoolsAppointedToRebalance, - AmmPoolsParams - } - - /// @notice Struct which contains owner address of IPOR Protocol Router. - struct OwnerStorage { - address owner; - } - - /// @notice Struct which contains appointed owner address of IPOR Protocol Router. - struct AppointedOwnerStorage { - address appointedOwner; - } - - /// @notice Struct which contains reentrancy status of IPOR Protocol Router. - struct ReentrancyStatusStorage { - uint256 value; - } - - /// @notice Struct which contains information about swap liquidators. - /// @dev First key is an asset (pool), second key is an liquidator address in the asset pool, - /// value is a flag to indicate whether account is a liquidator. - /// True - account is a liquidator, False - account is not a liquidator. - struct AmmSwapsLiquidatorsStorage { - mapping(address => mapping(address => bool)) value; - } - - /// @notice Struct which contains information about accounts appointed to rebalance. - /// @dev first key - asset address, second key - account address which is allowed to rebalance in the asset pool, - /// value - flag to indicate whether account is allowed to rebalance. True - allowed, False - not allowed. - struct AmmPoolsAppointedToRebalanceStorage { - mapping(address => mapping(address => bool)) value; - } - - struct AmmPoolsParamsValue { - /// @dev max liquidity pool balance in the asset pool, represented WITHOUT 18 decimals - uint32 maxLiquidityPoolBalance; - /// @dev The threshold for auto-rebalancing the pool. Value represented without 18 decimals. - uint32 autoRebalanceThreshold; - /// @dev asset management ratio, represented without 18 decimals, value represents percentage with 2 decimals - /// 65% = 6500, 99,99% = 9999, this is a percentage which stay in Amm Treasury in opposite to Asset Management - /// based on AMM Treasury balance (100%). - uint16 ammTreasuryAndAssetManagementRatio; - } - - /// @dev key - asset address, value - struct AmmOpenSwapParamsValue - struct AmmPoolsParamsStorage { - mapping(address => AmmPoolsParamsValue) value; - } - - /// @dev key - function sig, value - 1 if function is paused, 0 if not - struct RouterFunctionPausedStorage { - mapping(bytes4 => uint256) value; - } - - /// @notice Gets Ipor Protocol Router owner address. - function getOwner() internal pure returns (OwnerStorage storage owner) { - uint256 slot = _getStorageSlot(StorageId.Owner); - assembly { - owner.slot := slot - } - } - - /// @notice Gets Ipor Protocol Router appointed owner address. - function getAppointedOwner() internal pure returns (AppointedOwnerStorage storage appointedOwner) { - uint256 slot = _getStorageSlot(StorageId.AppointedOwner); - assembly { - appointedOwner.slot := slot - } - } - - /// @notice Gets Ipor Protocol Router reentrancy status. - function getReentrancyStatus() internal pure returns (ReentrancyStatusStorage storage reentrancyStatus) { - uint256 slot = _getStorageSlot(StorageId.ReentrancyStatus); - assembly { - reentrancyStatus.slot := slot - } - } - - /// @notice Gets information if function is paused in Ipor Protocol Router. - function getRouterFunctionPaused() internal pure returns (RouterFunctionPausedStorage storage paused) { - uint256 slot = _getStorageSlot(StorageId.RouterFunctionPaused); - assembly { - paused.slot := slot - } - } - - /// @notice Gets point to pause guardian storage. - function getPauseGuardianStorage() internal pure returns (mapping(address => bool) storage store) { - uint256 slot = _getStorageSlot(StorageId.PauseGuardian); - assembly { - store.slot := slot - } - } - - /// @notice Gets point to liquidators storage. - /// @return store - point to liquidators storage. - function getAmmSwapsLiquidatorsStorage() internal pure returns (AmmSwapsLiquidatorsStorage storage store) { - uint256 slot = _getStorageSlot(StorageId.AmmSwapsLiquidators); - assembly { - store.slot := slot - } - } - - /// @notice Gets point to accounts appointed to rebalance storage. - /// @return store - point to accounts appointed to rebalance storage. - function getAmmPoolsAppointedToRebalanceStorage() - internal - pure - returns (AmmPoolsAppointedToRebalanceStorage storage store) - { - uint256 slot = _getStorageSlot(StorageId.AmmPoolsAppointedToRebalance); - assembly { - store.slot := slot - } - } - - /// @notice Gets point to amm pools params storage. - /// @return store - point to amm pools params storage. - function getAmmPoolsParamsStorage() internal pure returns (AmmPoolsParamsStorage storage store) { - uint256 slot = _getStorageSlot(StorageId.AmmPoolsParams); - assembly { - store.slot := slot - } - } - - function _getStorageSlot(StorageId storageId) private pure returns (uint256 slot) { - return uint256(storageId) + STORAGE_SLOT_BASE; - } -} diff --git a/contracts/router/AccessControl.sol b/contracts/router/AccessControl.sol index 0cf46fcc4..8f222f367 100644 --- a/contracts/router/AccessControl.sol +++ b/contracts/router/AccessControl.sol @@ -2,7 +2,8 @@ pragma solidity 0.8.26; import {IporErrors} from "../libraries/errors/IporErrors.sol"; -import {StorageLib} from "../libraries/StorageLib.sol"; +import {StorageLibBaseV1} from "../base/libraries/StorageLibBaseV1.sol"; + import {PauseManager} from "../security/PauseManager.sol"; import {OwnerManager} from "../security/OwnerManager.sol"; import {IRouterAccessControl} from "../interfaces/IRouterAccessControl.sol"; @@ -29,7 +30,7 @@ contract AccessControl is IRouterAccessControl { /// @notice Checks if sender is appointed owner modifier onlyAppointedOwner() { - require(StorageLib.getAppointedOwner().appointedOwner == msg.sender, IporErrors.SENDER_NOT_APPOINTED_OWNER); + require(StorageLibBaseV1.getAppointedOwner().appointedOwner == msg.sender, IporErrors.SENDER_NOT_APPOINTED_OWNER); _; } @@ -72,7 +73,7 @@ contract AccessControl is IRouterAccessControl { /// @param functionSig Function signature /// @return 1 if function is paused, 0 otherwise function paused(bytes4 functionSig) external view override returns (uint256) { - return StorageLib.getRouterFunctionPaused().value[functionSig]; + return StorageLibBaseV1.getRouterFunctionPaused().value[functionSig]; } /// @notice Pauses list of functions in IporProtocolRouter @@ -80,7 +81,7 @@ contract AccessControl is IRouterAccessControl { function pause(bytes4[] calldata functionSigs) external override onlyPauseGuardian { uint256 len = functionSigs.length; for (uint256 i; i < len; ) { - StorageLib.getRouterFunctionPaused().value[functionSigs[i]] = 1; + StorageLibBaseV1.getRouterFunctionPaused().value[functionSigs[i]] = 1; unchecked { ++i; } @@ -92,7 +93,7 @@ contract AccessControl is IRouterAccessControl { function unpause(bytes4[] calldata functionSigs) external override onlyOwner { uint256 len = functionSigs.length; for (uint256 i; i < len; ) { - StorageLib.getRouterFunctionPaused().value[functionSigs[i]] = 0; + StorageLibBaseV1.getRouterFunctionPaused().value[functionSigs[i]] = 0; unchecked { ++i; } @@ -120,29 +121,29 @@ contract AccessControl is IRouterAccessControl { function _checkFunctionSigAndIsNotPause(bytes4 functionSig, bytes4 expectedSig) internal view returns (bool) { if (functionSig == expectedSig) { - require(StorageLib.getRouterFunctionPaused().value[functionSig] == 0, IporErrors.METHOD_PAUSED); + require(StorageLibBaseV1.getRouterFunctionPaused().value[functionSig] == 0, IporErrors.METHOD_PAUSED); return true; } return false; } function _onlyOwner() internal view { - require(StorageLib.getOwner().owner == msg.sender, IporErrors.CALLER_NOT_OWNER); + require(StorageLibBaseV1.getOwner().owner == msg.sender, IporErrors.CALLER_NOT_OWNER); } function _nonReentrantBefore() internal { // On the first call to nonReentrant, _status will be _NOT_ENTERED - require(StorageLib.getReentrancyStatus().value != _ENTERED, IporErrors.REENTRANCY); + require(StorageLibBaseV1.getReentrancyStatus().value != _ENTERED, IporErrors.REENTRANCY); // Any calls to nonReentrant after this point will fail - StorageLib.getReentrancyStatus().value = _ENTERED; + StorageLibBaseV1.getReentrancyStatus().value = _ENTERED; } function _nonReentrantAfter() internal { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) - if (StorageLib.getReentrancyStatus().value == _ENTERED) { - StorageLib.getReentrancyStatus().value = _NOT_ENTERED; + if (StorageLibBaseV1.getReentrancyStatus().value == _ENTERED) { + StorageLibBaseV1.getReentrancyStatus().value = _NOT_ENTERED; } } } diff --git a/contracts/router/IporProtocolRouterAbstract.sol b/contracts/router/IporProtocolRouterAbstract.sol index a446cfe40..f9afb9aca 100644 --- a/contracts/router/IporProtocolRouterAbstract.sol +++ b/contracts/router/IporProtocolRouterAbstract.sol @@ -6,7 +6,7 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U import {IProxyImplementation} from "../interfaces/IProxyImplementation.sol"; import {IporErrors} from "../libraries/errors/IporErrors.sol"; import {AccessControl} from "./AccessControl.sol"; -import {StorageLib} from "../libraries/StorageLib.sol"; +import {StorageLibBaseV1} from "../base/libraries/StorageLibBaseV1.sol"; import {OwnerManager} from "../security/OwnerManager.sol"; import {StorageSlotUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol"; @@ -24,7 +24,7 @@ abstract contract IporProtocolRouterAbstract is UUPSUpgradeable, AccessControl, function initialize(bool pausedInput) external initializer { __UUPSUpgradeable_init(); OwnerManager.transferOwnership(msg.sender); - StorageLib.getReentrancyStatus().value = _NOT_ENTERED; + StorageLibBaseV1.getReentrancyStatus().value = _NOT_ENTERED; } /// @notice Gets the implementation of the router @@ -69,7 +69,7 @@ abstract contract IporProtocolRouterAbstract is UUPSUpgradeable, AccessControl, if (routerEthBalance > 0) { /// @dev if view method then return back ETH is skipped - if (StorageLib.getReentrancyStatus().value == _ENTERED) { + if (StorageLibBaseV1.getReentrancyStatus().value == _ENTERED) { (bool success, ) = msg.sender.call{value: routerEthBalance}(""); if (!success) { diff --git a/contracts/security/OwnerManager.sol b/contracts/security/OwnerManager.sol index b70c4d2b5..c6004101c 100644 --- a/contracts/security/OwnerManager.sol +++ b/contracts/security/OwnerManager.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import "../libraries/StorageLib.sol"; import "../libraries/errors/IporErrors.sol"; +import {StorageLibBaseV1} from "../base/libraries/StorageLibBaseV1.sol"; /// @title Ipor Protocol Router Owner Manager library library OwnerManager { @@ -17,14 +17,14 @@ library OwnerManager { /// @notice Gets the current owner of Ipor Protocol Router function getOwner() internal view returns (address) { - return StorageLib.getOwner().owner; + return StorageLibBaseV1.getOwner().owner; } /// @notice Oppoint account to transfer ownership /// @param newAppointedOwner Address of appointed owner function appointToOwnership(address newAppointedOwner) internal { require(newAppointedOwner != address(0), IporErrors.WRONG_ADDRESS); - StorageLib.AppointedOwnerStorage storage appointedOwnerStorage = StorageLib.getAppointedOwner(); + StorageLibBaseV1.AppointedOwnerStorage storage appointedOwnerStorage = StorageLibBaseV1.getAppointedOwner(); appointedOwnerStorage.appointedOwner = newAppointedOwner; emit AppointedToTransferOwnership(newAppointedOwner); } @@ -32,7 +32,7 @@ library OwnerManager { /// @notice Confirm appointment to ownership /// @dev This is real transfer ownership in second step by appointed account function confirmAppointmentToOwnership() internal { - StorageLib.AppointedOwnerStorage storage appointedOwnerStorage = StorageLib.getAppointedOwner(); + StorageLibBaseV1.AppointedOwnerStorage storage appointedOwnerStorage = StorageLibBaseV1.getAppointedOwner(); appointedOwnerStorage.appointedOwner = address(0); transferOwnership(msg.sender); } @@ -40,13 +40,13 @@ library OwnerManager { /// @notice Renounce ownership function renounceOwnership() internal { transferOwnership(address(0)); - StorageLib.AppointedOwnerStorage storage appointedOwnerStorage = StorageLib.getAppointedOwner(); + StorageLibBaseV1.AppointedOwnerStorage storage appointedOwnerStorage = StorageLibBaseV1.getAppointedOwner(); appointedOwnerStorage.appointedOwner = address(0); } /// @notice Immediately transfers ownership function transferOwnership(address newOwner) internal { - StorageLib.OwnerStorage storage ownerStorage = StorageLib.getOwner(); + StorageLibBaseV1.OwnerStorage storage ownerStorage = StorageLibBaseV1.getOwner(); address oldOwner = ownerStorage.owner; ownerStorage.owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); diff --git a/contracts/security/PauseManager.sol b/contracts/security/PauseManager.sol index 56d84c9a3..c6de92ffd 100644 --- a/contracts/security/PauseManager.sol +++ b/contracts/security/PauseManager.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import "../libraries/StorageLib.sol"; +import {StorageLibBaseV1} from "../base/libraries/StorageLibBaseV1.sol"; /// @title Ipor Protocol Router Pause Manager library library PauseManager { @@ -17,7 +17,7 @@ library PauseManager { /// @param account Address of guardian /// @return true if account is Ipor Protocol Router pause guardian function isPauseGuardian(address account) internal view returns (bool) { - mapping(address => bool) storage pauseGuardians = StorageLib.getPauseGuardianStorage(); + mapping(address => bool) storage pauseGuardians = StorageLibBaseV1.getPauseGuardianStorage(); return pauseGuardians[account]; } @@ -29,7 +29,7 @@ library PauseManager { return; } - mapping(address => bool) storage pauseGuardians = StorageLib.getPauseGuardianStorage(); + mapping(address => bool) storage pauseGuardians = StorageLibBaseV1.getPauseGuardianStorage(); for (uint256 i; i < length; ) { pauseGuardians[newGuardians[i]] = true; @@ -49,7 +49,7 @@ library PauseManager { return; } - mapping(address => bool) storage pauseGuardians = StorageLib.getPauseGuardianStorage(); + mapping(address => bool) storage pauseGuardians = StorageLibBaseV1.getPauseGuardianStorage(); for (uint256 i; i < length; ) { pauseGuardians[guardians[i]] = false; diff --git a/test/AmmStorageLastOpenSwap.t.sol b/test/AmmStorageLastOpenSwap.t.sol index 31ce43aa3..8b4d7d4ff 100644 --- a/test/AmmStorageLastOpenSwap.t.sol +++ b/test/AmmStorageLastOpenSwap.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; import "../contracts/amm/AmmStorage.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -import "./TestCommons.sol"; +import "../test/TestCommons.sol"; contract SimpleTest is TestCommons { AmmStorage internal _ammStorage; diff --git a/test/IporLogic.t.sol b/test/IporLogic.t.sol index 47590e871..ce845f5fe 100644 --- a/test/IporLogic.t.sol +++ b/test/IporLogic.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "./TestCommons.sol"; +import "../test/TestCommons.sol"; import "../contracts/oracles/libraries/IporLogic.sol"; import "./utils/TestConstants.sol"; import "../contracts/interfaces/types/IporOracleTypes.sol"; diff --git a/test/IporProtocolRouter.t.sol b/test/IporProtocolRouter.t.sol index eb1697e84..bb3c20e06 100644 --- a/test/IporProtocolRouter.t.sol +++ b/test/IporProtocolRouter.t.sol @@ -1,8 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "./TestCommons.sol"; +import "../test/TestCommons.sol"; import "contracts/libraries/errors/IporErrors.sol"; +import {IporProtocolRouterEthereum} from "../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; contract IporProtocolRouterTest is TestCommons { IporProtocolFactory.IporProtocolConfig private _cfg; @@ -26,7 +27,7 @@ contract IporProtocolRouterTest is TestCommons { function testSwitchImplementation() public { // given IporProtocolRouterBuilder builder = new IporProtocolRouterBuilder(address(this)); - IporProtocolRouter router = builder.buildEmptyProxy(); + IporProtocolRouterEthereum router = builder.buildEmptyProxy(); address newImplementation = address(new EmptyRouterImplementation()); address oldImplementation = router.getImplementation(); @@ -239,365 +240,218 @@ contract IporProtocolRouterTest is TestCommons { function testCheckAddressesInConstructor() public { vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: address(0), ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: _userOne, ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, ammGovernanceService: _userOne, liquidityMiningLens: _userOne, powerTokenLens: _userOne, flowService: _userOne, stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _userOne, ammPoolsLens: address(0), - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: _userOne, ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, ammGovernanceService: _userOne, liquidityMiningLens: _userOne, powerTokenLens: _userOne, flowService: _userOne, stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne - }) - ); - vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ - ammSwapsLens: _userOne, - ammPoolsLens: _userOne, - ammPoolsLensStEth: address(0), - assetManagementLens: _userOne, - ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, - ammCloseSwapServiceUsdt: _userOne, - ammCloseSwapServiceUsdc: _userOne, - ammCloseSwapServiceDai: _userOne, - ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, - ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, - ammGovernanceService: _userOne, - liquidityMiningLens: _userOne, - powerTokenLens: _userOne, - flowService: _userOne, - stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _userOne, ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: address(0), ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, ammGovernanceService: _userOne, liquidityMiningLens: _userOne, powerTokenLens: _userOne, flowService: _userOne, stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _userOne, ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, - assetManagementLens: _userOne, - ammOpenSwapService: address(0), - ammOpenSwapServiceStEth: address(0), - ammCloseSwapServiceUsdt: _userOne, - ammCloseSwapServiceUsdc: _userOne, - ammCloseSwapServiceDai: _userOne, - ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, - ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, - ammGovernanceService: _userOne, - liquidityMiningLens: _userOne, - powerTokenLens: _userOne, - flowService: _userOne, - stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne - }) - ); - - vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ - ammSwapsLens: _userOne, - ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: _userOne, ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, - ammCloseSwapServiceUsdt: address(0), - ammCloseSwapServiceUsdc: _userOne, - ammCloseSwapServiceDai: _userOne, - ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: address(0), - ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, - ammGovernanceService: _userOne, - liquidityMiningLens: _userOne, - powerTokenLens: _userOne, - flowService: _userOne, - stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne - }) - ); - - vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ - ammSwapsLens: _userOne, - ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, - assetManagementLens: _userOne, - ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: address(0), - ammPoolsServiceStEth: _userOne, - ammGovernanceService: _userOne, - liquidityMiningLens: _userOne, - powerTokenLens: _userOne, - flowService: _userOne, - stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne - }) - ); - - vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ - ammSwapsLens: _userOne, - ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, - assetManagementLens: _userOne, - ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, - ammCloseSwapServiceUsdt: _userOne, - ammCloseSwapServiceUsdc: _userOne, - ammCloseSwapServiceDai: _userOne, - ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, - ammPoolsService: _userOne, - ammPoolsServiceStEth: address(0), ammGovernanceService: _userOne, liquidityMiningLens: _userOne, powerTokenLens: _userOne, flowService: _userOne, stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _userOne, ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: _userOne, ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, ammGovernanceService: address(0), liquidityMiningLens: _userOne, powerTokenLens: _userOne, flowService: _userOne, stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _userOne, ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: _userOne, ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, ammGovernanceService: _userOne, liquidityMiningLens: address(0), powerTokenLens: _userOne, flowService: _userOne, stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _userOne, ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: _userOne, ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, ammGovernanceService: _userOne, liquidityMiningLens: _userOne, powerTokenLens: address(0), flowService: _userOne, stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _userOne, ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: _userOne, ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, ammGovernanceService: _userOne, liquidityMiningLens: _userOne, powerTokenLens: _userOne, flowService: address(0), stakeService: _userOne, - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); vm.expectRevert("IPOR_000"); - new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _userOne, ammPoolsLens: _userOne, - ammPoolsLensStEth: _userOne, + ammPoolsLensBaseV1: _userOne, assetManagementLens: _userOne, ammOpenSwapService: _userOne, - ammOpenSwapServiceStEth: _userOne, ammCloseSwapServiceUsdt: _userOne, ammCloseSwapServiceUsdc: _userOne, ammCloseSwapServiceDai: _userOne, ammCloseSwapLens: _userOne, - ammCloseSwapServiceStEth: _userOne, ammPoolsService: _userOne, - ammPoolsServiceStEth: _userOne, ammGovernanceService: _userOne, liquidityMiningLens: _userOne, powerTokenLens: _userOne, flowService: _userOne, stakeService: address(0), - ammPoolsServiceWeEth: _userOne, - ammPoolsLensWeEth: _userOne, - ammPoolsServiceUsdm: _userOne, - ammPoolsLensUsdm: _userOne + stEth: _userOne, + weEth: _userOne, + usdm: _userOne }) ); } diff --git a/test/IporSwapLogic/IporSwapLogicCalculateSwapAmount.t.sol b/test/IporSwapLogic/IporSwapLogicCalculateSwapAmount.t.sol index 3850713ae..ea811961c 100644 --- a/test/IporSwapLogic/IporSwapLogicCalculateSwapAmount.t.sol +++ b/test/IporSwapLogic/IporSwapLogicCalculateSwapAmount.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../utils/DataUtils.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../mocks/MockIporSwapLogic.sol"; contract IporSwapLogicCalculateInterest is TestCommons, DataUtils { diff --git a/test/IporSwapLogic/SwapLogicCalculateInterest.t.sol b/test/IporSwapLogic/SwapLogicCalculateInterest.t.sol index 719827cc8..e19ddbd51 100644 --- a/test/IporSwapLogic/SwapLogicCalculateInterest.t.sol +++ b/test/IporSwapLogic/SwapLogicCalculateInterest.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../utils/DataUtils.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../mocks/MockIporSwapLogic.sol"; import "../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/IporSwapLogic/SwapLogicCalculateInterestFixed.t.sol b/test/IporSwapLogic/SwapLogicCalculateInterestFixed.t.sol index 87dcca894..9b003475d 100644 --- a/test/IporSwapLogic/SwapLogicCalculateInterestFixed.t.sol +++ b/test/IporSwapLogic/SwapLogicCalculateInterestFixed.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../utils/DataUtils.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../mocks/MockIporSwapLogic.sol"; diff --git a/test/IporSwapLogic/SwapLogicCalculateInterestFloating.t.sol b/test/IporSwapLogic/SwapLogicCalculateInterestFloating.t.sol index 3bef9e1c5..2c4d4cdae 100644 --- a/test/IporSwapLogic/SwapLogicCalculateInterestFloating.t.sol +++ b/test/IporSwapLogic/SwapLogicCalculateInterestFloating.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../utils/DataUtils.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../mocks/MockIporSwapLogic.sol"; diff --git a/test/IporSwapLogic/SwapLogicCalculateSwapPayFixedValue.t.sol b/test/IporSwapLogic/SwapLogicCalculateSwapPayFixedValue.t.sol index a55ece325..f544f7124 100644 --- a/test/IporSwapLogic/SwapLogicCalculateSwapPayFixedValue.t.sol +++ b/test/IporSwapLogic/SwapLogicCalculateSwapPayFixedValue.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../utils/DataUtils.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../mocks/MockIporSwapLogic.sol"; import "../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/IporSwapLogic/SwapLogicCalculateSwapReceiveFixedValue.t.sol b/test/IporSwapLogic/SwapLogicCalculateSwapReceiveFixedValue.t.sol index ad779cb08..abbd91669 100644 --- a/test/IporSwapLogic/SwapLogicCalculateSwapReceiveFixedValue.t.sol +++ b/test/IporSwapLogic/SwapLogicCalculateSwapReceiveFixedValue.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../utils/DataUtils.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../mocks/MockIporSwapLogic.sol"; import "../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/SoapIndicatorLogic.t.sol b/test/SoapIndicatorLogic.t.sol index 24db1ba6c..375e67bb4 100644 --- a/test/SoapIndicatorLogic.t.sol +++ b/test/SoapIndicatorLogic.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; -import "./TestCommons.sol"; +import "../test/TestCommons.sol"; import "./utils/TestConstants.sol"; import "../contracts/amm/libraries/SoapIndicatorLogic.sol"; import "../contracts/amm/libraries/SoapIndicatorRebalanceLogic.sol"; @@ -23,6 +23,8 @@ contract SoapIndicatorLogicTest is TestCommons { uint256 averageInterestRate; } + SoapIndicatorRebalanceLogicWrapper internal _wrapper; + function setUp() public { _admin = address(this); _userOne = _getUserAddress(1); @@ -30,6 +32,7 @@ contract SoapIndicatorLogicTest is TestCommons { _userThree = _getUserAddress(3); _liquidityProvider = _getUserAddress(4); _users = usersToArray(_admin, _userOne, _userTwo, _userThree, _liquidityProvider); + _wrapper = new SoapIndicatorRebalanceLogicWrapper(); } function testShouldCalculateInterestRateWhenOpenPositionSimpleCase1And18Decimals() public { @@ -88,9 +91,9 @@ contract SoapIndicatorLogicTest is TestCommons { soapIndicators.rebalanceTimestamp = uint32(block.timestamp); // when vm.expectRevert("IPOR_314"); - SoapIndicatorRebalanceLogic.calculateAverageInterestRateWhenCloseSwap( - soapIndicators.totalNotional, - soapIndicators.averageInterestRate, + _wrapper.calculateAverageInterestRateWhenCloseSwap( + uint128(soapIndicators.totalNotional), + uint64(soapIndicators.averageInterestRate), derivativeNotional, swapFixedInterestRate ); @@ -100,13 +103,12 @@ contract SoapIndicatorLogicTest is TestCommons { // given uint256 derivativeNotional = 40000 * TestConstants.D18; uint256 swapFixedInterestRate = TestConstants.PERCENTAGE_4_18DEC; - uint256 averageInterestRate = 2029718087; // when vm.expectRevert("IPOR_314"); - SoapIndicatorRebalanceLogic.calculateAverageInterestRateWhenCloseSwap( - derivativeNotional - 1, - 2029718087, + _wrapper.calculateAverageInterestRateWhenCloseSwap( + uint128(derivativeNotional - 1), + uint64(2029718087), derivativeNotional, swapFixedInterestRate ); @@ -114,7 +116,6 @@ contract SoapIndicatorLogicTest is TestCommons { function testShouldCalculateInterestRateEvenWhenClosePositionTotalNotionalAndAverageInterestRateTooLow() public { // given - uint256 derivativeNotional = 40000 * TestConstants.D18; uint256 swapFixedInterestRate = TestConstants.PERCENTAGE_4_18DEC; // when @@ -153,23 +154,18 @@ contract SoapIndicatorLogicTest is TestCommons { function testShouldRevertWhenCalculateTimestampIsGreaterThanOrEqualToLastRebalanceTimestamp() public { // when vm.expectRevert("IPOR_317"); - SoapIndicatorLogic.calculateHypotheticalInterestDelta( + _wrapper.calculateHypotheticalInterestDelta( TestConstants.ZERO, 1, - TestConstants.ZERO, - TestConstants.ZERO + uint128(TestConstants.ZERO), + uint64(TestConstants.ZERO) ); } function testShouldRevertWhenCalculateTimestampIsGreaterThanOrEqualToDerivativeOpenTimestamp() public { // when vm.expectRevert("IPOR_318"); - SoapIndicatorRebalanceLogic.calculateInterestPaidOut( - TestConstants.ZERO, - 1, - TestConstants.ZERO, - TestConstants.ZERO - ); + _wrapper.calculateInterestPaidOut(TestConstants.ZERO, 1, TestConstants.ZERO, TestConstants.ZERO); } function testShouldCalculateHypotheticalInterestDeltaWhenSimpleCase1And18Decimals() public { @@ -551,3 +547,53 @@ contract SoapIndicatorLogicTest is TestCommons { ); } } + +// Helper contract for testing library reverts +contract SoapIndicatorRebalanceLogicWrapper { + function calculateAverageInterestRateWhenCloseSwap( + uint128 totalNotional, + uint64 averageInterestRate, + uint256 derivativeNotional, + uint256 swapFixedInterestRate + ) external pure returns (uint256) { + return + uint256( + SoapIndicatorRebalanceLogic.calculateAverageInterestRateWhenCloseSwap( + totalNotional, + averageInterestRate, + derivativeNotional, + swapFixedInterestRate + ) + ); + } + + function calculateHypotheticalInterestDelta( + uint256 calculateTimestamp, + uint256 lastRebalanceTimestamp, + uint128 totalNotional, + uint64 averageInterestRate + ) external pure returns (uint256) { + return + SoapIndicatorLogic.calculateHypotheticalInterestDelta( + calculateTimestamp, + lastRebalanceTimestamp, + totalNotional, + averageInterestRate + ); + } + + function calculateInterestPaidOut( + uint256 calculateTimestamp, + uint256 derivativeOpenTimestamp, + uint256 derivativeNotional, + uint256 swapFixedInterestRate + ) external pure returns (uint256) { + return + SoapIndicatorRebalanceLogic.calculateInterestPaidOut( + calculateTimestamp, + derivativeOpenTimestamp, + derivativeNotional, + swapFixedInterestRate + ); + } +} diff --git a/test/amm-eth/EthRebalance.t.sol b/test/amm-eth/EthRebalance.t.sol new file mode 100644 index 000000000..2e167863e --- /dev/null +++ b/test/amm-eth/EthRebalance.t.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import "./TestEthMarketCommons.sol"; +import {IAmmPoolsServiceStEth} from "../../contracts/amm-eth/interfaces/IAmmPoolsServiceStEth.sol"; +import {IAmmGovernanceService} from "../../contracts/interfaces/IAmmGovernanceService.sol"; +import {IAmmGovernanceLens} from "../../contracts/interfaces/IAmmGovernanceLens.sol"; +import {AmmPoolsErrors} from "../../contracts/libraries/errors/AmmPoolsErrors.sol"; +import {IAmmGovernanceServiceBaseV1} from "../../contracts/base/interfaces/IAmmGovernanceServiceBaseV1.sol"; +import {StorageLibBaseV1} from "../../contracts/base/libraries/StorageLibBaseV1.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +/// @title Simple tests for rebalanceBetweenAmmTreasuryAndAssetManagementStEth router integration +/// @notice These tests verify that the router properly routes the rebalance function for stETH +contract EthRebalanceTest is TestEthMarketCommons { + function setUp() public { + vm.createSelectFork(vm.envString("ETHEREUM_PROVIDER_URL"), 20510653); + _init(); + _setupAssetManagement(); + } + + function _setupAssetManagement() internal { + vm.startPrank(owner); + // Configure governance pool with asset management (ammVault) enabled + IAmmGovernanceServiceBaseV1(iporProtocolRouter).setAmmGovernancePoolConfiguration( + stEth, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ + decimals: IERC20Metadata(stEth).decimals(), + ammStorage: ammStorageStEth, + ammTreasury: ammTreasuryStEth, + ammVault: newPlasmaVaultStEth, // Set to plasma vault instead of address(0) + ammPoolsTreasury: _getUserAddress(123), + ammPoolsTreasuryManager: _getUserAddress(123), + ammCharlieTreasury: _getUserAddress(123), + ammCharlieTreasuryManager: _getUserAddress(123) + }) + ); + + // Set proper AMM pools params with asset management ratio + IAmmGovernanceService(iporProtocolRouter).setAmmPoolsParams( + stEth, + 1000000000, // maxLiquidityPoolBalance + 1, // autoRebalanceThreshold + 5000 // ammTreasuryAndAssetManagementRatio (50%) + ); + vm.stopPrank(); + } + + function testShouldRevertWhenNotAppointedToRebalanceStEth() public { + // given + address user = _getUserAddress(22); + + // when & then + vm.expectRevert(bytes(AmmPoolsErrors.CALLER_NOT_APPOINTED_TO_REBALANCE)); + vm.prank(user); + IAmmPoolsServiceStEth(iporProtocolRouter).rebalanceBetweenAmmTreasuryAndAssetManagementStEth(); + } + + function testShouldAddUserToAppointedRebalanceStEth() public { + // given + address user = _getUserAddress(23); + + bool isAppointedBefore = IAmmGovernanceLens(iporProtocolRouter).isAppointedToRebalanceInAmm(stEth, user); + + // when + vm.prank(owner); + IAmmGovernanceService(iporProtocolRouter).addAppointedToRebalanceInAmm(stEth, user); + + // then + bool isAppointedAfter = IAmmGovernanceLens(iporProtocolRouter).isAppointedToRebalanceInAmm(stEth, user); + assertFalse(isAppointedBefore, "User should not be appointed before"); + assertTrue(isAppointedAfter, "User should be appointed after"); + } + + function testShouldRemoveUserFromAppointedRebalanceStEth() public { + // given + address user = _getUserAddress(24); + + vm.prank(owner); + IAmmGovernanceService(iporProtocolRouter).addAppointedToRebalanceInAmm(stEth, user); + + bool isAppointedBefore = IAmmGovernanceLens(iporProtocolRouter).isAppointedToRebalanceInAmm(stEth, user); + + // when + vm.prank(owner); + IAmmGovernanceService(iporProtocolRouter).removeAppointedToRebalanceInAmm(stEth, user); + + // then + bool isAppointedAfter = IAmmGovernanceLens(iporProtocolRouter).isAppointedToRebalanceInAmm(stEth, user); + assertTrue(isAppointedBefore, "User should be appointed before"); + assertFalse(isAppointedAfter, "User should not be appointed after"); + } + + function testShouldCallRebalanceFunctionThroughRouter() public { + // given + address user = _getUserAddress(25); + + vm.prank(owner); + IAmmGovernanceService(iporProtocolRouter).addAppointedToRebalanceInAmm(stEth, user); + + // when & then + // This test verifies that the router correctly routes to the rebalance function + // The function will revert during actual execution due to mock setup limitations, + // but we can verify it reaches the correct contract by checking the revert doesn't + // come from the router's INVALID_SIGNATURE error + vm.prank(user); + try IAmmPoolsServiceStEth(iporProtocolRouter).rebalanceBetweenAmmTreasuryAndAssetManagementStEth() { + // If it succeeds, that's also fine - means routing works + assertTrue(true); + } catch (bytes memory reason) { + // Verify it's not a router error (which would be "ROUTER_INVALID_SIGNATURE") + // Any other error means the router successfully routed to the pools service + string memory revertReason = string(reason); + assertFalse( + keccak256(abi.encodePacked(revertReason)) == keccak256(abi.encodePacked("ROUTER_INVALID_SIGNATURE")), + "Router should route to pools service, not return INVALID_SIGNATURE" + ); + } + } +} diff --git a/test/amm-eth/ProvideBatchExecutor.t.sol b/test/amm-eth/ProvideBatchExecutor.t.sol index bb45a3e31..1fd49403c 100644 --- a/test/amm-eth/ProvideBatchExecutor.t.sol +++ b/test/amm-eth/ProvideBatchExecutor.t.sol @@ -4,7 +4,8 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import "./TestEthMarketCommons.sol"; import "../../contracts/libraries/errors/AmmErrors.sol"; -import "../../contracts/chains/ethereum/router/IporProtocolRouter.sol"; +import "../../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; +import {IAmmPoolsLensBaseV1} from "../../contracts/base/interfaces/IAmmPoolsLensBaseV1.sol"; contract ProvideBatchExecutor is TestEthMarketCommons { function setUp() public { @@ -14,13 +15,13 @@ contract ProvideBatchExecutor is TestEthMarketCommons { function testShouldProvideLiquidityWhenBatchExecutorIsUsed() external { // given - uint userEthBalanceBefore = userOne.balance; - uint userIpstEthBalanceBefore = IERC20(ipstEth).balanceOf(userOne); - uint userStEthBalanceBefore = IStETH(stEth).balanceOf(userOne); - uint userWEthBalanceBefore = IERC20(wEth).balanceOf(userOne); + uint256 userEthBalanceBefore = userOne.balance; + uint256 userIpstEthBalanceBefore = IERC20(ipstEth).balanceOf(userOne); + uint256 userStEthBalanceBefore = IStETH(stEth).balanceOf(userOne); + uint256 userWEthBalanceBefore = IERC20(wEth).balanceOf(userOne); - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); - uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); + uint256 exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); + uint256 ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); bytes[] memory requestData = new bytes[](3); requestData[0] = abi.encodeWithSelector( @@ -42,16 +43,16 @@ contract ProvideBatchExecutor is TestEthMarketCommons { // when vm.prank(userOne); - IporProtocolRouter(iporProtocolRouter).batchExecutor{value: 150e18}(requestData); + IporProtocolRouterEthereum(iporProtocolRouter).batchExecutor{value: 150e18}(requestData); // then - uint userEthBalanceAfter = userOne.balance; - uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); - uint userStEthBalanceAfter = IStETH(stEth).balanceOf(userOne); - uint userWethBalanceAfter = IERC20(wEth).balanceOf(userOne); + uint256 userEthBalanceAfter = userOne.balance; + uint256 userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); + uint256 userStEthBalanceAfter = IStETH(stEth).balanceOf(userOne); + uint256 userWethBalanceAfter = IERC20(wEth).balanceOf(userOne); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); - uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); + uint256 exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); + uint256 ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); assertEq( userEthBalanceAfter, diff --git a/test/amm-eth/ProvideEth.t.sol b/test/amm-eth/ProvideEth.t.sol index 4990b70bd..a5f10ea95 100644 --- a/test/amm-eth/ProvideEth.t.sol +++ b/test/amm-eth/ProvideEth.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import "./TestEthMarketCommons.sol"; import "../../contracts/libraries/errors/AmmErrors.sol"; +import {IAmmPoolsLensBaseV1} from "../../contracts/base/interfaces/IAmmPoolsLensBaseV1.sol"; contract ProvideEth is TestEthMarketCommons { event ProvideLiquidityEth( @@ -95,7 +96,7 @@ contract ProvideEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when vm.prank(userOne); @@ -106,7 +107,7 @@ contract ProvideEth is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq(userEthBalanceBefore, 900_000e18, "user balance of Eth should be 900_000e18"); assertEq(userWEthBalanceAfter, 899_900e18, "user balance of Eth should be 899_900e18"); @@ -128,7 +129,7 @@ contract ProvideEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when vm.prank(userOne); @@ -142,7 +143,7 @@ contract ProvideEth is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq(userEthBalanceBefore, 900_000e18, "user balance of Eth should be 900_000e18"); assertEq(userEthBalanceAfter, 899_900e18, "user balance of Eth should be 899_900e18"); @@ -166,7 +167,7 @@ contract ProvideEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when vm.prank(userOne); @@ -178,7 +179,7 @@ contract ProvideEth is TestEthMarketCommons { uint userTwoEthBalanceAfter = userTwo.balance; uint userTwoIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userTwo); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq(userOneEthBalanceBefore, 900_000e18, "user balance of Eth should be 900_000e18"); assertEq(userOneEthBalanceAfter, 899_900e18, "user balance of Eth should be 899_900e18"); @@ -212,7 +213,7 @@ contract ProvideEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 10e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when for (uint i; i < 10; ++i) { @@ -228,7 +229,7 @@ contract ProvideEth is TestEthMarketCommons { uint userTwoEthBalanceAfter = userTwo.balance; uint userTwoIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userTwo); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq(userOneEthBalanceBefore, 900_000e18, "user balance of wEth should be 50_000e18"); assertEq(userOneEthBalanceAfter, 899_900e18, "user balance of wEth should be 49900e18"); @@ -279,7 +280,7 @@ contract ProvideEth is TestEthMarketCommons { function testShouldEmitProvideLiquidityEthBeneficiaryIsNotSender() public { // given uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint256 amountStEth = 99999999999999999999; uint256 ipTokenAmount = IporMath.division(amountStEth * 1e18, exchangeRateBefore); @@ -362,7 +363,7 @@ contract ProvideEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); /// @dev direct eth transfer vm.prank(userOne); @@ -382,7 +383,7 @@ contract ProvideEth is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint routerEthBalance = address(iporProtocolRouter).balance; @@ -410,7 +411,7 @@ contract ProvideEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); /// @dev direct eth transfer vm.prank(userTwo); @@ -430,7 +431,7 @@ contract ProvideEth is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint routerEthBalance = address(iporProtocolRouter).balance; diff --git a/test/amm-eth/ProvideStEth.t.sol b/test/amm-eth/ProvideStEth.t.sol index 28dd65620..f646bfed1 100644 --- a/test/amm-eth/ProvideStEth.t.sol +++ b/test/amm-eth/ProvideStEth.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import "./TestEthMarketCommons.sol"; import "../../contracts/libraries/errors/AmmErrors.sol"; +import {IAmmPoolsLensBaseV1} from "../../contracts/base/interfaces/IAmmPoolsLensBaseV1.sol"; contract ProvideStEthTest is TestEthMarketCommons { event ProvideLiquidityStEth( @@ -34,7 +35,7 @@ contract ProvideStEthTest is TestEthMarketCommons { //given //when - uint exchangeRate = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRate = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); //then assertEq(exchangeRate, 1e18, "exchangeRate should be 1"); } @@ -82,7 +83,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when vm.prank(userOne); @@ -93,7 +94,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq( userStEthBalanceBefore - provideAmount, @@ -124,7 +125,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when vm.prank(userOne); @@ -136,7 +137,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint userTwoStEthBalanceAfter = IStETH(stEth).balanceOf(userTwo); uint userTwoIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userTwo); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq( userOneStEthBalanceBefore - provideAmount, @@ -169,7 +170,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 10e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when for (uint i; i < 10; ++i) { @@ -185,7 +186,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint userTwoStEthBalanceAfter = IStETH(stEth).balanceOf(userTwo); uint userTwoIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userTwo); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq( userOneStEthBalanceBefore, @@ -227,8 +228,8 @@ contract ProvideStEthTest is TestEthMarketCommons { console2.log("IERC20(ipstEth): ", IERC20(ipstEth).totalSupply()); console2.log( - "IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(): ", - IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate() + "IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth): ", + IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth) ); console2.log("IStETH(stEth).balanceOf(ammTreasuryStEth): ", IStETH(stEth).balanceOf(ammTreasuryStEth)); // 49_999 999999999999999999 (userOne Balance) @@ -253,7 +254,7 @@ contract ProvideStEthTest is TestEthMarketCommons { function testShouldEmitProvideLiquidityStEthBeneficiaryIsNotSender() public { // given uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint256 ipTokenAmount = IporMath.division(provideAmount * 1e18, exchangeRateBefore); vm.prank(userOne); @@ -337,7 +338,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); /// @dev direct eth transfer vm.prank(userOne); @@ -354,7 +355,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint routerEthBalance = address(iporProtocolRouter).balance; @@ -386,7 +387,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); /// @dev direct eth transfer vm.prank(userTwo); @@ -403,7 +404,7 @@ contract ProvideStEthTest is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint routerEthBalance = address(iporProtocolRouter).balance; diff --git a/test/amm-eth/ProvideWEth.t.sol b/test/amm-eth/ProvideWEth.t.sol index c296cc76e..018cc9ab5 100644 --- a/test/amm-eth/ProvideWEth.t.sol +++ b/test/amm-eth/ProvideWEth.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import "./TestEthMarketCommons.sol"; import "../../contracts/libraries/errors/AmmErrors.sol"; +import {IAmmPoolsLensBaseV1} from "../../contracts/base/interfaces/IAmmPoolsLensBaseV1.sol"; contract ProvideWEth is TestEthMarketCommons { event ProvideLiquidityEth( @@ -74,7 +75,7 @@ contract ProvideWEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when vm.prank(userOne); @@ -85,7 +86,7 @@ contract ProvideWEth is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq(userWEthBalanceBefore, 50_000e18, "user balance of wEth should be 50_000e18"); assertEq(userWEthBalanceAfter, 49_900e18, "user balance of wEth should be 49_900e18"); @@ -109,7 +110,7 @@ contract ProvideWEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when vm.prank(userOne); @@ -121,7 +122,7 @@ contract ProvideWEth is TestEthMarketCommons { uint userTwoWEthBalanceAfter = IWETH9(wEth).balanceOf(userTwo); uint userTwoIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userTwo); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq(userOneWEthBalanceBefore, 50_000e18, "user balance of wEth should be 50_000e18"); assertEq(userOneWEthBalanceAfter, 49_900e18, "user balance of wEth should be 49_900e18"); @@ -155,7 +156,7 @@ contract ProvideWEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 10e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); // when for (uint i; i < 10; ++i) { @@ -171,7 +172,7 @@ contract ProvideWEth is TestEthMarketCommons { uint userTwoWEthBalanceAfter = IWETH9(wEth).balanceOf(userTwo); uint userTwoIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userTwo); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq(userOneWEthBalanceBefore, 50_000e18, "user balance of wEth should be 50_000e18"); assertEq(userOneWEthBalanceAfter, 49900e18, "user balance of wEth should be 49900e18"); @@ -233,7 +234,7 @@ contract ProvideWEth is TestEthMarketCommons { uint provideAmount = 100e18; uint256 amountStEth = 99999999999999999999; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint256 ipTokenAmount = IporMath.division(amountStEth * 1e18, exchangeRateBefore); vm.prank(userOne); @@ -311,7 +312,7 @@ contract ProvideWEth is TestEthMarketCommons { } function testShouldProvideEthToWhenBeneficiaryIsNotSenderAndReturnRestOfEthAndDirectTransferEthBeforeByTheSameUser() - external + external { // given uint userEthBalanceBefore = userOne.balance; @@ -319,7 +320,7 @@ contract ProvideWEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); /// @dev direct eth transfer vm.prank(userOne); @@ -336,7 +337,7 @@ contract ProvideWEth is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint routerEthBalance = address(iporProtocolRouter).balance; @@ -345,11 +346,7 @@ contract ProvideWEth is TestEthMarketCommons { assertEq(userEthBalanceBefore, 900_000e18, "user balance of Eth should be 900_000e18"); assertEq(userEthBalanceAfter, 900_000e18, "user balance of Eth should be 900_000e18"); assertEq(userIpstEthBalanceBefore, 0, "user ipstEth balance should be 0"); - assertEq( - userIpstEthBalanceAfter, - 99999999999999999999, - "user ipstEth balance should be 99999999999999999999" - ); + assertEq(userIpstEthBalanceAfter, 99999999999999999999, "user ipstEth balance should be 99999999999999999999"); assertEq(ammTreasuryStEthBalanceBefore, 0, "amm treasury balance should be 0"); assertEq( ammTreasuryStEthBalanceAfter, @@ -360,7 +357,7 @@ contract ProvideWEth is TestEthMarketCommons { } function testShouldProvideEthToWhenBeneficiaryIsNotSenderAndReturnRestOfEthAndDirectTransferEthBeforeByDifferentUser() - external + external { // given uint userEthBalanceBefore = userOne.balance; @@ -368,7 +365,7 @@ contract ProvideWEth is TestEthMarketCommons { uint ammTreasuryStEthBalanceBefore = IStETH(stEth).balanceOf(ammTreasuryStEth); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); /// @dev direct eth transfer vm.prank(userTwo); @@ -385,7 +382,7 @@ contract ProvideWEth is TestEthMarketCommons { uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); uint ammTreasuryStEthBalanceAfter = IStETH(stEth).balanceOf(ammTreasuryStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint routerEthBalance = address(iporProtocolRouter).balance; @@ -394,11 +391,7 @@ contract ProvideWEth is TestEthMarketCommons { assertEq(userEthBalanceBefore, 900_000e18, "user balance of Eth should be 900_000e18"); assertEq(userEthBalanceAfter, 900_007e18, "user balance of Eth should be 900_007e18"); assertEq(userIpstEthBalanceBefore, 0, "user ipstEth balance should be 0"); - assertEq( - userIpstEthBalanceAfter, - 99999999999999999999, - "user ipstEth balance should be 99999999999999999999" - ); + assertEq(userIpstEthBalanceAfter, 99999999999999999999, "user ipstEth balance should be 99999999999999999999"); assertEq(ammTreasuryStEthBalanceBefore, 0, "amm treasury balance should be 0"); assertEq( ammTreasuryStEthBalanceAfter, diff --git a/test/amm-eth/RedeemStEth.t.sol b/test/amm-eth/RedeemStEth.t.sol index 6de97837c..21634e3e3 100644 --- a/test/amm-eth/RedeemStEth.t.sol +++ b/test/amm-eth/RedeemStEth.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import "./TestEthMarketCommons.sol"; import "../../contracts/libraries/errors/AmmErrors.sol"; +import {IAmmPoolsLensBaseV1} from "../../contracts/base/interfaces/IAmmPoolsLensBaseV1.sol"; contract RedeemStEth is TestEthMarketCommons { function setUp() public { @@ -73,7 +74,7 @@ contract RedeemStEth is TestEthMarketCommons { // given uint userStEthBalanceBefore = IStETH(stEth).balanceOf(userOne); uint userIpstEthBalanceBefore = IERC20(ipstEth).balanceOf(userOne); - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint redeemAmount = 100e18; // when @@ -83,7 +84,7 @@ contract RedeemStEth is TestEthMarketCommons { // then uint userStEthBalanceAfter = IStETH(stEth).balanceOf(userOne); uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertTrue(userStEthBalanceBefore < userStEthBalanceAfter, "user balance of stEth should increase"); assertTrue(userIpstEthBalanceBefore > userIpstEthBalanceAfter, "user ipstEth balance should decrease"); @@ -95,7 +96,7 @@ contract RedeemStEth is TestEthMarketCommons { uint userStEthBalanceBefore = IStETH(stEth).balanceOf(userOne); uint userTwoStEthBalanceBefore = IStETH(stEth).balanceOf(userTwo); uint userIpstEthBalanceBefore = IERC20(ipstEth).balanceOf(userOne); - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); uint redeemAmount = 100e18; // when @@ -106,7 +107,7 @@ contract RedeemStEth is TestEthMarketCommons { uint userStEthBalanceAfter = IStETH(stEth).balanceOf(userOne); uint userTwoStEthBalanceAfter = IStETH(stEth).balanceOf(userTwo); uint userIpstEthBalanceAfter = IERC20(ipstEth).balanceOf(userOne); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouter).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouter).getIpTokenExchangeRate(stEth); assertEq(userStEthBalanceBefore, userStEthBalanceAfter, "user balance of stEth should not change"); assertTrue(userTwoStEthBalanceBefore < userTwoStEthBalanceAfter, "user balance of stEth should increase"); diff --git a/test/amm-eth/TestEthMarketCommons.sol b/test/amm-eth/TestEthMarketCommons.sol index 99417da52..4723164e3 100644 --- a/test/amm-eth/TestEthMarketCommons.sol +++ b/test/amm-eth/TestEthMarketCommons.sol @@ -2,16 +2,24 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "forge-std/Test.sol"; import "../mocks/EmptyRouterImplementation.sol"; import "../../contracts/tokens/IpToken.sol"; -import "../../contracts/amm-eth/AmmPoolsServiceStEth.sol"; -import "../../contracts/amm-eth/AmmPoolsLensStEth.sol"; +import "../../contracts/amm-eth/interfaces/IStETH.sol"; +import "../../contracts/amm-eth/interfaces/IWETH9.sol"; +import "../../contracts/amm-eth/interfaces/IAmmPoolsServiceStEth.sol"; import "../../contracts/interfaces/IAmmGovernanceLens.sol"; -import "../../contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol"; -import "../../contracts/chains/ethereum/router/IporProtocolRouter.sol"; +import "../../contracts/interfaces/IAmmGovernanceService.sol"; +import "../../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; import "../../contracts/base/amm/AmmStorageBaseV1.sol"; -import "../../contracts/base/amm/AmmTreasuryBaseV1.sol"; +import "../../contracts/base/amm/AmmTreasuryBaseV2.sol"; +import "../../contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol"; +import "../../contracts/base/amm/services/AmmPoolsLensBaseV1.sol"; +import {IAmmGovernanceServiceBaseV1} from "../../contracts/base/interfaces/IAmmGovernanceServiceBaseV1.sol"; +import {StorageLibBaseV1} from "../../contracts/base/libraries/StorageLibBaseV1.sol"; +import {AmmPoolsServiceStEth} from "../../contracts/chains/ethereum/amm-stEth/AmmPoolsServiceStEth.sol"; +import {MockPlasmaVault} from "../mocks/tokens/MockPlasmaVault.sol"; contract TestEthMarketCommons is Test { address internal defaultAnvilAddress = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; @@ -35,9 +43,11 @@ contract TestEthMarketCommons is Test { address payable public iporProtocolRouter; address public ammTreasuryStEth; address public ammStorageStEth; + address public newPlasmaVaultStEth; address public ammGovernanceService; address public ammPoolsServiceStEth; address public ammPoolsLensStEth; + address public ammPoolsLensBaseV1; // tests data address public userOne = address(11); @@ -48,14 +58,19 @@ contract TestEthMarketCommons is Test { _createEmptyRouterImplementation(); _createIpstEth(); + _createPlasmaVaults(); _createDummyAmmTreasuryStEth(); _createAmmStorageStEth(); + _upgradeAmmTreasuryStEth(); _createAmmPoolServiceStEth(); - _createAmmPoolsLensStEth(); + _createAmmPoolsLensBaseV1(); _createAmmGovernanceService(); _updateIporRouterImplementation(); + _setupAmmGovernancePoolConfiguration(); + _setupAssetServices(); + _setupAssetLensData(); _setupPools(); _setupUser(userOne, 50_000e18); @@ -63,6 +78,10 @@ contract TestEthMarketCommons is Test { _setupUser(userThree, 10_000e18); } + function _createPlasmaVaults() internal { + newPlasmaVaultStEth = address(new MockPlasmaVault(IERC20(stEth), "ipstETHfusion", "ipstETHfusion")); + } + function _createEmptyRouterImplementation() private { vm.prank(owner); address implementation = address(new EmptyRouterImplementation()); @@ -80,7 +99,7 @@ contract TestEthMarketCommons is Test { function _createDummyAmmTreasuryStEth() private { vm.prank(owner); - AmmTreasuryBaseV1 impl = new AmmTreasuryBaseV1(stEth, iporProtocolRouter, defaultAnvilAddress); + AmmTreasuryBaseV2 impl = new AmmTreasuryBaseV2(stEth, iporProtocolRouter, defaultAnvilAddress, newPlasmaVaultStEth); ERC1967Proxy proxy = _constructProxy(address(impl)); ammTreasuryStEth = address(proxy); } @@ -93,15 +112,8 @@ contract TestEthMarketCommons is Test { } function _upgradeAmmTreasuryStEth() private { - address impl = address(new AmmTreasuryBaseV1(stEth, iporProtocolRouter, ammStorageStEth)); - AmmTreasuryBaseV1(ammTreasuryStEth).upgradeTo(impl); - } - - function _createAmmTreasuryStEth() private { - vm.prank(owner); - AmmTreasuryBaseV1 impl = new AmmTreasuryBaseV1(stEth, iporProtocolRouter, userOne); - ERC1967Proxy proxy = _constructProxy(address(impl)); - ammTreasuryStEth = address(proxy); + address impl = address(new AmmTreasuryBaseV2(stEth, iporProtocolRouter, ammStorageStEth, newPlasmaVaultStEth)); + AmmTreasuryBaseV2(ammTreasuryStEth).upgradeTo(impl); } function _createAmmPoolServiceStEth() private { @@ -112,118 +124,40 @@ contract TestEthMarketCommons is Test { ipstEth, ammTreasuryStEth, ammStorageStEth, + newPlasmaVaultStEth, iporOracle, iporProtocolRouter, - redeemFeeRateEth + redeemFeeRateEth, + 1 ); ammPoolsServiceStEth = address(pool); vm.stopPrank(); } - function _createAmmPoolsLensStEth() private { + function _createAmmPoolsLensBaseV1() private { vm.startPrank(owner); - AmmPoolsLensStEth lens = new AmmPoolsLensStEth(stEth, ipstEth, ammTreasuryStEth, ammStorageStEth, iporOracle); - ammPoolsLensStEth = address(lens); + ammPoolsLensBaseV1 = address(new AmmPoolsLensBaseV1({iporOracle_: iporOracle})); vm.stopPrank(); } function _createAmmGovernanceService() private { vm.startPrank(owner); - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory daiConfig = IAmmGovernanceLens - .AmmGovernancePoolConfiguration( - DAI, - 18, - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123) - ); - - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory usdcConfig = IAmmGovernanceLens - .AmmGovernancePoolConfiguration( - USDC, - 6, - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123) - ); - - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory usdtConfig = IAmmGovernanceLens - .AmmGovernancePoolConfiguration( - USDT, - 6, - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123) - ); - - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory stEthConfig = IAmmGovernanceLens - .AmmGovernancePoolConfiguration( - stEth, - 18, - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123) - ); - - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory weEthConfig = IAmmGovernanceLens - .AmmGovernancePoolConfiguration( - weETH, - 18, - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123) - ); - - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory usdmConfig = IAmmGovernanceLens - .AmmGovernancePoolConfiguration( - USDM, - 18, - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123) - ); - - ammGovernanceService = address(new AmmGovernanceService(usdtConfig, usdcConfig, daiConfig, stEthConfig, weEthConfig, usdmConfig)); + ammGovernanceService = address(new AmmGovernanceServiceBaseV1()); vm.stopPrank(); } function _updateIporRouterImplementation() internal { vm.startPrank(owner); - IporProtocolRouter newImplementation = new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + IporProtocolRouterEthereum newImplementation = new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: _getUserAddress(123), ammPoolsLens: _getUserAddress(123), + ammPoolsLensBaseV1: ammPoolsLensBaseV1, assetManagementLens: _getUserAddress(123), ammOpenSwapService: _getUserAddress(123), - ammOpenSwapServiceStEth: _getUserAddress(123), ammCloseSwapServiceUsdt: _getUserAddress(123), ammCloseSwapServiceUsdc: _getUserAddress(123), ammCloseSwapServiceDai: _getUserAddress(123), - ammCloseSwapServiceStEth: _getUserAddress(123), ammCloseSwapLens: _getUserAddress(123), ammPoolsService: _getUserAddress(123), ammGovernanceService: ammGovernanceService, @@ -231,16 +165,63 @@ contract TestEthMarketCommons is Test { powerTokenLens: _getUserAddress(123), flowService: _getUserAddress(123), stakeService: _getUserAddress(123), - ammPoolsServiceStEth: ammPoolsServiceStEth, - ammPoolsLensStEth: ammPoolsLensStEth, - ammPoolsServiceWeEth: _getUserAddress(123), - ammPoolsLensWeEth: _getUserAddress(123), - ammPoolsServiceUsdm: _getUserAddress(123), - ammPoolsLensUsdm: _getUserAddress(123) + stEth: stEth, + weEth: weETH, + usdm: USDM }) ); - IporProtocolRouter(iporProtocolRouter).upgradeTo(address(newImplementation)); + IporProtocolRouterEthereum(iporProtocolRouter).upgradeTo(address(newImplementation)); + vm.stopPrank(); + } + + function _setupAmmGovernancePoolConfiguration() private { + vm.startPrank(owner); + // Setup pool configuration for stEth + IAmmGovernanceServiceBaseV1(iporProtocolRouter).setAmmGovernancePoolConfiguration( + stEth, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ + decimals: 18, + ammStorage: ammStorageStEth, + ammTreasury: ammTreasuryStEth, + ammVault: address(0), + ammPoolsTreasury: _getUserAddress(123), + ammPoolsTreasuryManager: _getUserAddress(123), + ammCharlieTreasury: _getUserAddress(123), + ammCharlieTreasuryManager: _getUserAddress(123) + }) + ); + vm.stopPrank(); + } + + function _setupAssetServices() private { + vm.startPrank(owner); + // Setup AssetServices for stEth + IAmmGovernanceServiceBaseV1(iporProtocolRouter).setAssetServices( + stEth, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: ammPoolsServiceStEth, + ammOpenSwapService: address(0), + ammCloseSwapService: address(0) + }) + ); + vm.stopPrank(); + } + + function _setupAssetLensData() private { + vm.startPrank(owner); + // Setup AssetLensData for stEth + IAmmGovernanceServiceBaseV1(iporProtocolRouter).setAssetLensData( + stEth, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 18, + ipToken: ipstEth, + ammStorage: ammStorageStEth, + ammTreasury: ammTreasuryStEth, + ammVault: address(0), + spread: address(0) + }) + ); vm.stopPrank(); } diff --git a/test/amm-usdm/ethereum/ProvideUsdmEthereum.t.sol b/test/amm-usdm/ethereum/ProvideUsdmEthereum.t.sol index 0c725f3a6..2a4ee5af2 100644 --- a/test/amm-usdm/ethereum/ProvideUsdmEthereum.t.sol +++ b/test/amm-usdm/ethereum/ProvideUsdmEthereum.t.sol @@ -8,9 +8,9 @@ import "../../../contracts/libraries/ProvideLiquidityEvents.sol"; import "../../../contracts/libraries/errors/AmmErrors.sol"; import "../../../contracts/libraries/errors/AmmPoolsErrors.sol"; import {IAmmPoolsServiceUsdm} from "../../../contracts/amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol"; -import {IAmmPoolsLensUsdm} from "../../../contracts/amm-usdm/interfaces/IAmmPoolsLensUsdm.sol"; import {IAmmGovernanceService} from "../../../contracts/interfaces/IAmmGovernanceService.sol"; import {UsdmTestForkCommonEthereum} from "./UsdmTestForkCommonEthereum.sol"; +import {IAmmPoolsLens} from "../../../contracts/interfaces/IAmmPoolsLens.sol"; contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { @@ -26,7 +26,7 @@ contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { //given //when - uint exchangeRate = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint exchangeRate = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); //then assertEq(exchangeRate, 1e18, "exchangeRate should be 1"); } @@ -74,7 +74,7 @@ contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { uint userIpUsdmBalanceBefore = IERC20(ipUsdm).balanceOf(userOne); uint ammTreasuryUsdmBalanceBefore = IERC20(USDM).balanceOf(ammTreasuryUsdmProxy); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); // when vm.prank(userOne); @@ -85,7 +85,7 @@ contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { uint userIpUsdmBalanceAfter = IERC20(ipUsdm).balanceOf(userOne); uint ammTreasuryUsdmBalanceAfter = IERC20(USDM).balanceOf(ammTreasuryUsdmProxy); - uint exchangeRateAfter = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); assertEq(userUsdmBalanceBefore - provideAmount, userUsdmBalanceAfter, "user balance of usdm should decrease"); assertEq( @@ -119,7 +119,7 @@ contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { uint ammTreasuryUsdmBalanceBefore = IERC20(USDM).balanceOf(ammTreasuryUsdmProxy); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); // when vm.prank(userOne); @@ -131,7 +131,7 @@ contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { uint userTwoUsdmBalanceAfter = IERC20(USDM).balanceOf(userTwo); uint userTwoIpUsdmBalanceAfter = IERC20(ipUsdm).balanceOf(userTwo); uint ammTreasuryUsdmBalanceAfter = IERC20(USDM).balanceOf(ammTreasuryUsdmProxy); - uint exchangeRateAfter = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); assertEq( userOneUsdmBalanceBefore - provideAmount, @@ -172,7 +172,7 @@ contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { uint ammTreasuryUsdmBalanceBefore = IERC20(USDM).balanceOf(ammTreasuryUsdmProxy); uint provideAmount = 10e18; - uint exchangeRateBefore = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); // when for (uint i; i < 10; ++i) { @@ -188,7 +188,7 @@ contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { uint userTwoUsdmBalanceAfter = IERC20(USDM).balanceOf(userTwo); uint userTwoIpUsdmBalanceAfter = IERC20(ipUsdm).balanceOf(userTwo); uint ammTreasuryUsdmBalanceAfter = IERC20(USDM).balanceOf(ammTreasuryUsdmProxy); - uint exchangeRateAfter = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); assertEq( userOneUsdmBalanceBefore, @@ -251,7 +251,7 @@ contract ProvideUsdmEthereumTest is UsdmTestForkCommonEthereum { address userTwo = _getUserAddress(33); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); uint256 ipTokenAmount = IporMath.division(provideAmount * 1e18, exchangeRateBefore); vm.prank(userOne); diff --git a/test/amm-usdm/ethereum/UsdmForkAmmUsdmExchangeRateEthereum.t.sol b/test/amm-usdm/ethereum/UsdmForkAmmUsdmExchangeRateEthereum.t.sol index e44398ef9..a45717340 100644 --- a/test/amm-usdm/ethereum/UsdmForkAmmUsdmExchangeRateEthereum.t.sol +++ b/test/amm-usdm/ethereum/UsdmForkAmmUsdmExchangeRateEthereum.t.sol @@ -6,11 +6,10 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "../../../contracts/interfaces/IAmmCloseSwapServiceWstEth.sol"; import "../../../contracts/interfaces/types/AmmTypes.sol"; import {UsdmTestForkCommonEthereum} from "./UsdmTestForkCommonEthereum.sol"; -import {IAmmPoolsLensUsdm} from "../../../contracts/amm-usdm/interfaces/IAmmPoolsLensUsdm.sol"; import {IAmmPoolsServiceUsdm} from "../../../contracts/amm-usdm/interfaces/IAmmPoolsServiceUsdm.sol"; +import {IAmmPoolsLens} from "../../../contracts/interfaces/IAmmPoolsLens.sol"; contract UsdmForkAmmUsdmExchangeRateEthereumTest is UsdmTestForkCommonEthereum { - function testShouldNotChangeExchangeRateWhenProvideLiquidityUsdmToAmmPoolUsdmForUsdm() public { // given _init(); @@ -19,14 +18,14 @@ contract UsdmForkAmmUsdmExchangeRateEthereumTest is UsdmTestForkCommonEthereum { uint256 provideAmount = 10_000 * 1e18; - uint256 exchangeRateBefore = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); // when vm.prank(user); IAmmPoolsServiceUsdm(IporProtocolRouterProxy).provideLiquidityUsdmToAmmPoolUsdm(user, provideAmount); //then - uint256 exchangeRateAfter = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -39,7 +38,7 @@ contract UsdmForkAmmUsdmExchangeRateEthereumTest is UsdmTestForkCommonEthereum { uint256 provideAmount = 1 ether; - uint256 exchangeRateBefore = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); // when vm.startPrank(user); @@ -49,19 +48,18 @@ contract UsdmForkAmmUsdmExchangeRateEthereumTest is UsdmTestForkCommonEthereum { vm.stopPrank(); //then - uint256 exchangeRateAfter = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); assertLt(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } - function testShouldNOTChangeExchangeRateWhenProvideLiquidityAndRedeemBecauseOfRedeemFeeIsZEROUsdm() - public - { + function testShouldNOTChangeExchangeRateWhenProvideLiquidityAndRedeemBecauseOfRedeemFeeIsZEROUsdm() public { // given _init(); vm.startPrank(IporProtocolOwner); _createAmmPoolsServiceUsdm(0); _updateIporRouterImplementation(); + _setupAssetServices(); vm.stopPrank(); address user = _getUserAddress(22); @@ -69,7 +67,7 @@ contract UsdmForkAmmUsdmExchangeRateEthereumTest is UsdmTestForkCommonEthereum { uint256 provideAmount = 100e18; - uint256 exchangeRateBefore = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); // when vm.startPrank(user); @@ -80,8 +78,8 @@ contract UsdmForkAmmUsdmExchangeRateEthereumTest is UsdmTestForkCommonEthereum { vm.stopPrank(); //then - uint256 exchangeRateAfter = IAmmPoolsLensUsdm(IporProtocolRouterProxy).getIpUsdmExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLens(IporProtocolRouterProxy).getIpTokenExchangeRate(USDM); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } -} \ No newline at end of file +} diff --git a/test/amm-usdm/ethereum/UsdmTestForkCommonEthereum.sol b/test/amm-usdm/ethereum/UsdmTestForkCommonEthereum.sol index eb3e2446f..b9771389b 100644 --- a/test/amm-usdm/ethereum/UsdmTestForkCommonEthereum.sol +++ b/test/amm-usdm/ethereum/UsdmTestForkCommonEthereum.sol @@ -10,10 +10,13 @@ import "../../../contracts/tokens/IpToken.sol"; import "../../../contracts/base/amm/AmmTreasuryBaseV1.sol"; import "../../../contracts/base/amm/AmmStorageBaseV1.sol"; import "../../../contracts/amm-usdm/AmmPoolsServiceUsdm.sol"; -import "../../../contracts/amm-usdm/AmmPoolsLensUsdm.sol"; -import "../../../contracts/chains/ethereum/router/IporProtocolRouter.sol"; -import "../../../contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol"; +import "../../../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; import "../../arbitrum/usdm/WUsdmMock.sol"; +import {AmmGovernanceServiceBaseV1} from "../../../contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol"; +import {AmmPoolsLensBaseV1} from "../../../contracts/base/amm/services/AmmPoolsLensBaseV1.sol"; +import {IAmmGovernanceServiceBaseV1} from "../../../contracts/base/interfaces/IAmmGovernanceServiceBaseV1.sol"; +import {StorageLibBaseV1} from "../../../contracts/base/libraries/StorageLibBaseV1.sol"; +import "../../../contracts/interfaces/IAmmGovernanceService.sol"; contract UsdmTestForkCommonEthereum is Test { address constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7; @@ -73,18 +76,28 @@ contract UsdmTestForkCommonEthereum is Test { address ammPoolsLensUsdm; address ammGovernanceService; + address ammPoolsLensBaseV1; + + uint256 messageSignerPrivateKey; + address messageSignerAddress; function _init() internal { vm.createSelectFork(vm.envString("ETHEREUM_PROVIDER_URL"), 19520045); + messageSignerPrivateKey = 0x12341234; + messageSignerAddress = vm.addr(messageSignerPrivateKey); + vm.startPrank(IporProtocolOwner); _createIpUsdm(); _createAmmStorageUsdm(); _createTreasuryUsdm(); _createAmmPoolsServiceUsdm(5 * 1e15); - _createAmmPoolsLensUsdm(); + _createAmmPoolsLensBaseV1(); _createAmmGovernanceService(); _updateIporRouterImplementation(); + _setupAmmGovernancePoolConfiguration(); + _setupAssetServices(); + _setupAssetLensData(); _setupPools(); vm.stopPrank(); _provideInitialLiquidity(); @@ -125,115 +138,86 @@ contract UsdmTestForkCommonEthereum is Test { ); } - function _createAmmPoolsLensUsdm() private { - ammPoolsLensUsdm = address( - new AmmPoolsLensUsdm(USDM, ipUsdm, ammTreasuryUsdmProxy, ammStorageUsdmProxy, IporOracleProxy) - ); + function _createAmmPoolsLensBaseV1() private { + ammPoolsLensBaseV1 = address(new AmmPoolsLensBaseV1({iporOracle_: IporOracleProxy})); } function _createAmmGovernanceService() internal { - ammGovernanceService = address( - new AmmGovernanceService({ - usdtPoolCfg: IAmmGovernanceLens.AmmGovernancePoolConfiguration({ - asset: USDT, - decimals: IERC20MetadataUpgradeable(USDT).decimals(), - ammStorage: AmmStorageUsdtProxy, - ammTreasury: AmmTreasuryUsdtProxy, - ammVault: AssetManagementUsdtProxy, - ammPoolsTreasury: IporProtocolOwner, - ammPoolsTreasuryManager: IporProtocolOwner, - ammCharlieTreasury: IporProtocolOwner, - ammCharlieTreasuryManager: IporProtocolOwner - }), - usdcPoolCfg: IAmmGovernanceLens.AmmGovernancePoolConfiguration({ - asset: USDC, - decimals: IERC20MetadataUpgradeable(USDC).decimals(), - ammStorage: AmmStorageUsdcProxy, - ammTreasury: AmmTreasuryUsdcProxy, - ammVault: AssetManagementUsdcProxy, - ammPoolsTreasury: IporProtocolOwner, - ammPoolsTreasuryManager: IporProtocolOwner, - ammCharlieTreasury: IporProtocolOwner, - ammCharlieTreasuryManager: IporProtocolOwner - }), - daiPoolCfg: IAmmGovernanceLens.AmmGovernancePoolConfiguration({ - asset: DAI, - decimals: IERC20MetadataUpgradeable(DAI).decimals(), - ammStorage: AmmStorageDaiProxy, - ammTreasury: AmmTreasuryDaiProxy, - ammVault: AssetManagementDaiProxy, - ammPoolsTreasury: IporProtocolOwner, - ammPoolsTreasuryManager: IporProtocolOwner, - ammCharlieTreasury: IporProtocolOwner, - ammCharlieTreasuryManager: IporProtocolOwner - }), - stEthPoolCfg: IAmmGovernanceLens.AmmGovernancePoolConfiguration({ - asset: stETH, - decimals: IERC20MetadataUpgradeable(stETH).decimals(), - ammStorage: AmmStorageStEthProxy, - ammTreasury: AmmTreasuryStEthProxy, - ammVault: address(0), - ammPoolsTreasury: IporProtocolOwner, - ammPoolsTreasuryManager: IporProtocolOwner, - ammCharlieTreasury: IporProtocolOwner, - ammCharlieTreasuryManager: IporProtocolOwner - }), - weEthPoolCfg: IAmmGovernanceLens.AmmGovernancePoolConfiguration({ - asset: weETH, - decimals: IERC20MetadataUpgradeable(weETH).decimals(), - ammStorage: AmmStorageWeEthProxy, - ammTreasury: AmmTreasuryWeEthProxy, - ammVault: address(0), - ammPoolsTreasury: IporProtocolOwner, - ammPoolsTreasuryManager: IporProtocolOwner, - ammCharlieTreasury: IporProtocolOwner, - ammCharlieTreasuryManager: IporProtocolOwner - }), - usdmPoolCfg: IAmmGovernanceLens.AmmGovernancePoolConfiguration({ - asset: USDM, - decimals: IERC20MetadataUpgradeable(USDM).decimals(), - ammStorage: ammStorageUsdmProxy, - ammTreasury: ammTreasuryUsdmProxy, - ammVault: address(0), - ammPoolsTreasury: IporProtocolOwner, - ammPoolsTreasuryManager: IporProtocolOwner, - ammCharlieTreasury: IporProtocolOwner, - ammCharlieTreasuryManager: IporProtocolOwner - }) + ammGovernanceService = address(new AmmGovernanceServiceBaseV1()); + } + + function _updateIporRouterImplementation() internal { + IporProtocolRouterEthereum.DeployedContracts memory deployedContracts = IporProtocolRouterEthereum + .DeployedContracts({ + ammSwapsLens: AmmSwapsLens, + ammPoolsLens: AmmPoolsLens, + ammPoolsLensBaseV1: ammPoolsLensBaseV1, + assetManagementLens: AssetManagementLens, + ammOpenSwapService: AmmOpenSwapService, + ammCloseSwapServiceUsdt: AmmCloseSwapServiceUsdt, + ammCloseSwapServiceUsdc: AmmCloseSwapServiceUsdc, + ammCloseSwapServiceDai: AmmCloseSwapServiceDai, + ammCloseSwapLens: AmmCloseSwapLens, + ammPoolsService: AmmPoolsService, + ammGovernanceService: ammGovernanceService, + liquidityMiningLens: LiquidityMiningLens, + powerTokenLens: PowerTokenLens, + flowService: FlowsService, + stakeService: StakeService, + stEth: stETH, + weEth: weETH, + usdm: USDM + }); + + address iporProtocolRouterImpl = address(new IporProtocolRouterEthereum(deployedContracts)); + IporProtocolRouterEthereum(IporProtocolRouterProxy).upgradeTo(iporProtocolRouterImpl); + } + + function _setupAmmGovernancePoolConfiguration() private { + // Setup message signer + IAmmGovernanceServiceBaseV1(IporProtocolRouterProxy).setMessageSigner(messageSignerAddress); + + // Setup pool configuration for USDM + IAmmGovernanceServiceBaseV1(IporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + USDM, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ + decimals: 18, + ammStorage: ammStorageUsdmProxy, + ammTreasury: ammTreasuryUsdmProxy, + ammVault: address(0), // USDM doesn't have asset management + ammPoolsTreasury: address(0), + ammPoolsTreasuryManager: address(0), + ammCharlieTreasury: address(0), + ammCharlieTreasuryManager: address(0) }) ); } - function _updateIporRouterImplementation() internal { + function _setupAssetServices() internal { + // Setup AssetServices for USDM + IAmmGovernanceServiceBaseV1(IporProtocolRouterProxy).setAssetServices( + USDM, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: ammPoolsServiceUsdm, + ammOpenSwapService: address(0), + ammCloseSwapService: address(0) + }) + ); + } - IporProtocolRouter.DeployedContracts memory deployedContracts = IporProtocolRouter - .DeployedContracts({ - ammSwapsLens: AmmSwapsLens, - ammPoolsLens: AmmPoolsLens, - assetManagementLens: AssetManagementLens, - ammOpenSwapService: AmmOpenSwapService, - ammOpenSwapServiceStEth: AmmOpenSwapServiceStEth, - ammCloseSwapServiceUsdt: AmmCloseSwapServiceUsdt, - ammCloseSwapServiceUsdc: AmmCloseSwapServiceUsdc, - ammCloseSwapServiceDai: AmmCloseSwapServiceDai, - ammCloseSwapServiceStEth: AmmCloseSwapServiceStEth, - ammCloseSwapLens: AmmCloseSwapLens, - ammPoolsService: AmmPoolsService, - ammGovernanceService: ammGovernanceService, - liquidityMiningLens: LiquidityMiningLens, - powerTokenLens: PowerTokenLens, - flowService: FlowsService, - stakeService: StakeService, - ammPoolsServiceStEth: AmmPoolsServiceEth, - ammPoolsLensStEth: AmmPoolsLensEth, - ammPoolsServiceWeEth: AmmPoolsServiceWeEth, - ammPoolsLensWeEth: AmmPoolsLensWeEth, - ammPoolsServiceUsdm: ammPoolsServiceUsdm, - ammPoolsLensUsdm: ammPoolsLensUsdm - }); - - address iporProtocolRouterImpl = address(new IporProtocolRouter(deployedContracts)); - IporProtocolRouter(IporProtocolRouterProxy).upgradeTo(iporProtocolRouterImpl); + function _setupAssetLensData() private { + // Setup AssetLensData for USDM + IAmmGovernanceServiceBaseV1(IporProtocolRouterProxy).setAssetLensData( + USDM, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 18, + ipToken: ipUsdm, + ammStorage: ammStorageUsdmProxy, + ammTreasury: ammTreasuryUsdmProxy, + ammVault: address(0), // USDM doesn't have asset management + spread: address(0) // USDM doesn't have spread yet + }) + ); } function _setupPools() internal { diff --git a/test/amm-weEth/ProvideWeEth.t.sol b/test/amm-weEth/ProvideWeEth.t.sol index 7bbb21388..08441deee 100644 --- a/test/amm-weEth/ProvideWeEth.t.sol +++ b/test/amm-weEth/ProvideWeEth.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.26; import "./WeEthTestForkCommon.sol"; import "../../contracts/libraries/errors/AmmErrors.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {IAmmPoolsLensBaseV1} from "../../contracts/base/amm/services/AmmPoolsLensBaseV1.sol"; contract ProvideWeEthTest is WeEthTestForkCommon { address userOne; @@ -18,7 +19,7 @@ contract ProvideWeEthTest is WeEthTestForkCommon { //given //when - uint exchangeRate = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint exchangeRate = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); //then assertEq(exchangeRate, 1e18, "exchangeRate should be 1"); } @@ -64,39 +65,40 @@ contract ProvideWeEthTest is WeEthTestForkCommon { // given uint userWeEthBalanceBefore = IERC20(weETH).balanceOf(userOne); uint userIpWeEthBalanceBefore = IERC20(ipWeEth).balanceOf(userOne); - uint ammTreasuryWeEthBalanceBefore = IERC20(weETH).balanceOf(ammTreasuryWeEthProxy); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.prank(userOne); IAmmPoolsServiceWeEth(IporProtocolRouterProxy).provideLiquidityWeEthToAmmPoolWeEth(userOne, provideAmount); // then - uint userWeEthBalanceAfter = IERC20(weETH).balanceOf(userOne); - uint userIpWeEthBalanceAfter = IERC20(ipWeEth).balanceOf(userOne); - uint ammTreasuryWeEthBalanceAfter = IERC20(weETH).balanceOf(ammTreasuryWeEthProxy); - - uint exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); - assertEq( userWeEthBalanceBefore - provideAmount, - userWeEthBalanceAfter, + IERC20(weETH).balanceOf(userOne), "user balance of weEth should decrease" ); assertEq( userIpWeEthBalanceBefore + provideAmount, - userIpWeEthBalanceAfter, + IERC20(ipWeEth).balanceOf(userOne), "user ipstEth balance should increase" ); - assertEq(userIpWeEthBalanceAfter, provideAmount, "user ipWeEth balance should be equal to provideAmount"); - assertEq(ammTreasuryWeEthBalanceBefore, 0, "amm treasury balance should be 0"); assertEq( - ammTreasuryWeEthBalanceAfter, + IERC20(ipWeEth).balanceOf(userOne), + provideAmount, + "user ipWeEth balance should be equal to provideAmount" + ); + // With asset management enabled and 50% ratio, funds are split between treasury and vault + assertEq( + IERC20(weETH).balanceOf(ammTreasuryWeEthProxy) + IERC20(weETH).balanceOf(plasmaVaultWeEth), 100000000000000000000, - "amm treasury balance should be 100000000000000000000" + "total balance (treasury + vault) should be 100000000000000000000" + ); + assertEq( + exchangeRateBefore, + IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH), + "exchangeRate should not change" ); - assertEq(exchangeRateBefore, exchangeRateAfter, "exchangeRate should not change"); } function testShouldProvideWeEthToOtherAddressWhenBeneficiaryIsNotSender() external { @@ -108,43 +110,47 @@ contract ProvideWeEthTest is WeEthTestForkCommon { uint userOneIpWeEthBalanceBefore = IERC20(ipWeEth).balanceOf(userOne); uint userTwoWeEthBalanceBefore = IERC20(weETH).balanceOf(userTwo); uint userTwoIpWeEthBalanceBefore = IERC20(ipWeEth).balanceOf(userTwo); - uint ammTreasuryWeEthBalanceBefore = IERC20(weETH).balanceOf(ammTreasuryWeEthProxy); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.prank(userOne); IAmmPoolsServiceWeEth(IporProtocolRouterProxy).provideLiquidityWeEthToAmmPoolWeEth(userTwo, provideAmount); // then - uint userOneWeEthBalanceAfter = IERC20(weETH).balanceOf(userOne); - uint userOneIpWeEthBalanceAfter = IERC20(ipWeEth).balanceOf(userOne); - uint userTwoWeEthBalanceAfter = IERC20(weETH).balanceOf(userTwo); - uint userTwoIpWeEthBalanceAfter = IERC20(ipWeEth).balanceOf(userTwo); - uint ammTreasuryWeEthBalanceAfter = IERC20(weETH).balanceOf(ammTreasuryWeEthProxy); - uint exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); - assertEq( userOneWeEthBalanceBefore - provideAmount, - userOneWeEthBalanceAfter, + IERC20(weETH).balanceOf(userOne), "user balance of usdm should decrease" ); - assertEq(userOneIpWeEthBalanceBefore, userOneIpWeEthBalanceAfter, "user ipWeEth balance should not change"); - assertEq(userTwoWeEthBalanceBefore, userTwoWeEthBalanceAfter, "user balance of usdm should not change"); + assertEq( + userOneIpWeEthBalanceBefore, + IERC20(ipWeEth).balanceOf(userOne), + "user ipWeEth balance should not change" + ); + assertEq(userTwoWeEthBalanceBefore, IERC20(weETH).balanceOf(userTwo), "user balance of usdm should not change"); assertEq( userTwoIpWeEthBalanceBefore + provideAmount, - userTwoIpWeEthBalanceAfter, + IERC20(ipWeEth).balanceOf(userTwo), "user ipWeEth balance should increase" ); - assertEq(userTwoIpWeEthBalanceAfter, provideAmount, "user ipWeEth balance should be equal to provideAmount"); - assertEq(ammTreasuryWeEthBalanceBefore, 0, "amm treasury balance should be 0"); assertEq( - ammTreasuryWeEthBalanceAfter, + IERC20(ipWeEth).balanceOf(userTwo), + provideAmount, + "user ipWeEth balance should be equal to provideAmount" + ); + // With asset management enabled and 50% ratio, funds are split between treasury and vault + assertEq( + IERC20(weETH).balanceOf(ammTreasuryWeEthProxy) + IERC20(weETH).balanceOf(plasmaVaultWeEth), 100000000000000000000, - "amm treasury balance should be 100000000000000000000" + "total balance (treasury + vault) should be 100000000000000000000" + ); + assertEq( + exchangeRateBefore, + IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH), + "exchangeRate should not change" ); - assertEq(exchangeRateBefore, exchangeRateAfter, "exchangeRate should not change"); } function testShouldProvide10TimesWeEth() external { @@ -157,10 +163,9 @@ contract ProvideWeEthTest is WeEthTestForkCommon { uint userOneIpWeEthBalanceBefore = IERC20(ipWeEth).balanceOf(userOne); uint userTwoWeEthBalanceBefore = IERC20(weETH).balanceOf(userTwo); uint userTwoIpWeEthBalanceBefore = IERC20(ipWeEth).balanceOf(userTwo); - uint ammTreasuryWeEthBalanceBefore = IERC20(weETH).balanceOf(ammTreasuryWeEthProxy); uint provideAmount = 10e18; - uint exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when for (uint i; i < 10; ++i) { @@ -171,26 +176,19 @@ contract ProvideWeEthTest is WeEthTestForkCommon { } // then - uint userOneWeEthBalanceAfter = IERC20(weETH).balanceOf(userOne); - uint userOneIpWeEthBalanceAfter = IERC20(ipWeEth).balanceOf(userOne); - uint userTwoWeEthBalanceAfter = IERC20(weETH).balanceOf(userTwo); - uint userTwoIpWeEthBalanceAfter = IERC20(ipWeEth).balanceOf(userTwo); - uint ammTreasuryWeEthBalanceAfter = IERC20(weETH).balanceOf(ammTreasuryWeEthProxy); - uint exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); - assertEq( userOneWeEthBalanceBefore, 97062378226296843608896, "user balance of WeEth should be 97062378226296843608896" ); assertEq( - userOneWeEthBalanceAfter, + IERC20(weETH).balanceOf(userOne), 96962378226296843608896, "user balance of WeEth should be 96962378226296843608896" ); assertEq( userOneIpWeEthBalanceBefore + provideAmount * 10, - userOneIpWeEthBalanceAfter, + IERC20(ipWeEth).balanceOf(userOne), "user ipWeEth balance should increase" ); assertEq( @@ -199,21 +197,25 @@ contract ProvideWeEthTest is WeEthTestForkCommon { "user balance of WeEth should be 97062378226296843608896" ); assertEq( - userTwoWeEthBalanceAfter, + IERC20(weETH).balanceOf(userTwo), 96962378226296843608896, "user balance of WeEth should be 96962378226296843608896" ); assertEq( userTwoIpWeEthBalanceBefore + provideAmount * 10, - userTwoIpWeEthBalanceAfter, + IERC20(ipWeEth).balanceOf(userTwo), "user ipWeEth balance should increase" ); - assertEq(exchangeRateBefore, exchangeRateAfter, "exchangeRate should not change"); - assertEq(ammTreasuryWeEthBalanceBefore, 0, "amm treasury balance should be 0"); assertEq( - ammTreasuryWeEthBalanceAfter, + exchangeRateBefore, + IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH), + "exchangeRate should not change" + ); + // With asset management enabled and 50% ratio, funds are split between treasury and vault + assertEq( + IERC20(weETH).balanceOf(ammTreasuryWeEthProxy) + IERC20(weETH).balanceOf(plasmaVaultWeEth), 200000000000000000000, - "amm treasury balance should be 200000000000000000000" + "total balance (treasury + vault) should be 200000000000000000000" ); } @@ -235,7 +237,7 @@ contract ProvideWeEthTest is WeEthTestForkCommon { address userTwo = _getUserAddress(33); uint provideAmount = 100e18; - uint exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); uint256 ipTokenAmount = IporMath.division(provideAmount * 1e18, exchangeRateBefore); vm.prank(userOne); @@ -268,6 +270,9 @@ contract ProvideWeEthTest is WeEthTestForkCommon { uint exchangeRate = 1000000000000000000; + // Note: With asset management, funds might be rebalanced automatically + // The redeem should still work correctly by withdrawing from vault if needed + vm.prank(userTwo); vm.expectEmit(true, true, true, true); //then diff --git a/test/amm-weEth/WeEthForkAmmGovernanceServiceTest.t.sol b/test/amm-weEth/WeEthForkAmmGovernanceServiceTest.t.sol index e994cc642..4778a6cce 100644 --- a/test/amm-weEth/WeEthForkAmmGovernanceServiceTest.t.sol +++ b/test/amm-weEth/WeEthForkAmmGovernanceServiceTest.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "../../contracts/interfaces/IAmmGovernanceService.sol"; -import "../../contracts/interfaces/IAmmGovernanceService.sol"; +import "../../contracts/libraries/errors/IporErrors.sol"; import "./WeEthTestForkCommon.sol"; contract WeEthForkAmmGovernanceServiceTest is WeEthTestForkCommon { @@ -11,23 +11,28 @@ contract WeEthForkAmmGovernanceServiceTest is WeEthTestForkCommon { _init(); } - function testShouldNotWithdrawFromAssetManagementWeEth() public { + function testShouldNotWithdrawFromAssetManagementWeEthWhenVaultIsEmpty() public { //given _init(); // when - vm.expectRevert(bytes(IporErrors.ASSET_NOT_SUPPORTED)); + // With asset management enabled, trying to withdraw from empty vault should fail with ERC4626 error + vm.expectRevert(bytes("ERC4626: withdraw more than max")); vm.prank(IporProtocolOwner); IAmmGovernanceService(IporProtocolRouterProxy).withdrawFromAssetManagement(weETH, 100 * 1e18); } - function testShouldNotWithdrawAllFromAssetManagementWeEth() public { + function testShouldWithdrawAllFromAssetManagementWeEthWhenVaultIsEmpty() public { //given _init(); // when - vm.expectRevert(bytes(IporErrors.ASSET_NOT_SUPPORTED)); + // With asset management enabled, withdrawAll from empty vault should succeed (withdrawing 0) vm.prank(IporProtocolOwner); IAmmGovernanceService(IporProtocolRouterProxy).withdrawAllFromAssetManagement(weETH); + + // then + // Should not revert, just withdraw 0 + assertEq(IERC20(weETH).balanceOf(plasmaVaultWeEth), 0, "vault balance should still be 0"); } } diff --git a/test/amm-weEth/WeEthForkAmmWeEthExchangeRate.t.sol b/test/amm-weEth/WeEthForkAmmWeEthExchangeRate.t.sol index 8bb3f19cc..aa5d27b19 100644 --- a/test/amm-weEth/WeEthForkAmmWeEthExchangeRate.t.sol +++ b/test/amm-weEth/WeEthForkAmmWeEthExchangeRate.t.sol @@ -5,6 +5,7 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "./WeEthTestForkCommon.sol"; import "../../contracts/interfaces/IAmmCloseSwapServiceWstEth.sol"; import "../../contracts/interfaces/types/AmmTypes.sol"; +import {IAmmPoolsLensBaseV1} from "../../contracts/base/interfaces/IAmmPoolsLensBaseV1.sol"; contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { function testShouldNotChangeExchangeRateWhenProvideLiquidityWeEthToAmmPoolWeEthForWeEth() public { @@ -15,14 +16,14 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { uint256 provideAmount = 10_000 * 1e18; - uint256 exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.prank(user); IAmmPoolsServiceWeEth(IporProtocolRouterProxy).provideLiquidityWeEthToAmmPoolWeEth(user, provideAmount); //then - uint256 exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -35,14 +36,14 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { uint256 provideAmount = 10_000 * 1e18; - uint256 exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.prank(user); IAmmPoolsServiceWeEth(IporProtocolRouterProxy).provideLiquidity(weETH, weETH, user, provideAmount); //then - uint256 exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -55,14 +56,14 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { uint256 provideAmount = 10_000 * 1e18; - uint256 exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.prank(user); IAmmPoolsServiceWeEth(IporProtocolRouterProxy).provideLiquidity(weETH, eETH, user, provideAmount); //then - uint256 exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -75,14 +76,14 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { uint256 provideAmount = 10_000 * 1e18; - uint256 exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.prank(user); IAmmPoolsServiceWeEth(IporProtocolRouterProxy).provideLiquidity(weETH, wETH, user, provideAmount); //then - uint256 exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -95,7 +96,7 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { uint256 provideAmount = 10_000 * 1e18; - uint256 exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.prank(user); @@ -107,7 +108,7 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -121,7 +122,7 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { uint256 provideAmount = 1e18; - uint256 exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.startPrank(user); @@ -132,7 +133,7 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { vm.stopPrank(); //then - uint256 exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); assertLt(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -152,7 +153,7 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { uint256 provideAmount = 100e18; - uint256 exchangeRateBefore = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateBefore = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); // when vm.startPrank(user); @@ -163,7 +164,7 @@ contract UsdmForkAmmWstEthExchangeRateTest is WeEthTestForkCommon { vm.stopPrank(); //then - uint256 exchangeRateAfter = IAmmPoolsLensWeEth(IporProtocolRouterProxy).getIpWeEthExchangeRate(); + uint256 exchangeRateAfter = IAmmPoolsLensBaseV1(IporProtocolRouterProxy).getIpTokenExchangeRate(weETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } diff --git a/test/amm-weEth/WeEthRebalance.t.sol b/test/amm-weEth/WeEthRebalance.t.sol new file mode 100644 index 000000000..b19a15c8b --- /dev/null +++ b/test/amm-weEth/WeEthRebalance.t.sol @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import "./WeEthTestForkCommon.sol"; +import {IAmmPoolsServiceWeEth} from "../../contracts/amm-weEth/interfaces/IAmmPoolsServiceWeEth.sol"; +import {IAmmGovernanceService} from "../../contracts/interfaces/IAmmGovernanceService.sol"; +import {IAmmGovernanceLens} from "../../contracts/interfaces/IAmmGovernanceLens.sol"; +import {AmmPoolsErrors} from "../../contracts/libraries/errors/AmmPoolsErrors.sol"; + +/// @title Simple tests for rebalanceBetweenAmmTreasuryAndAssetManagementWeEth router integration +/// @notice These tests verify that the router properly routes the rebalance function for weETH +contract WeEthRebalanceTest is WeEthTestForkCommon { + function setUp() public { + _init(); + } + + function testShouldRevertWhenNotAppointedToRebalanceWeEth() public { + // given + address user = _getUserAddress(22); + + // when & then + vm.expectRevert(bytes(AmmPoolsErrors.CALLER_NOT_APPOINTED_TO_REBALANCE)); + vm.prank(user); + IAmmPoolsServiceWeEth(IporProtocolRouterProxy).rebalanceBetweenAmmTreasuryAndAssetManagementWeEth(); + } + + function testShouldAddUserToAppointedRebalanceWeEth() public { + // given + address user = _getUserAddress(23); + + bool isAppointedBefore = IAmmGovernanceLens(IporProtocolRouterProxy).isAppointedToRebalanceInAmm(weETH, user); + + // when + vm.prank(IporProtocolOwner); + IAmmGovernanceService(IporProtocolRouterProxy).addAppointedToRebalanceInAmm(weETH, user); + + // then + bool isAppointedAfter = IAmmGovernanceLens(IporProtocolRouterProxy).isAppointedToRebalanceInAmm(weETH, user); + assertFalse(isAppointedBefore, "User should not be appointed before"); + assertTrue(isAppointedAfter, "User should be appointed after"); + } + + function testShouldRemoveUserFromAppointedRebalanceWeEth() public { + // given + address user = _getUserAddress(24); + + vm.prank(IporProtocolOwner); + IAmmGovernanceService(IporProtocolRouterProxy).addAppointedToRebalanceInAmm(weETH, user); + + bool isAppointedBefore = IAmmGovernanceLens(IporProtocolRouterProxy).isAppointedToRebalanceInAmm(weETH, user); + + // when + vm.prank(IporProtocolOwner); + IAmmGovernanceService(IporProtocolRouterProxy).removeAppointedToRebalanceInAmm(weETH, user); + + // then + bool isAppointedAfter = IAmmGovernanceLens(IporProtocolRouterProxy).isAppointedToRebalanceInAmm(weETH, user); + assertTrue(isAppointedBefore, "User should be appointed before"); + assertFalse(isAppointedAfter, "User should not be appointed after"); + } + + function testShouldCallRebalanceFunctionThroughRouter() public { + // given + address user = _getUserAddress(25); + + vm.prank(IporProtocolOwner); + IAmmGovernanceService(IporProtocolRouterProxy).addAppointedToRebalanceInAmm(weETH, user); + + // when & then + // This test verifies that the router correctly routes to the rebalance function + // The function will succeed if vault is empty (rebalancing 0) + vm.prank(user); + try IAmmPoolsServiceWeEth(IporProtocolRouterProxy).rebalanceBetweenAmmTreasuryAndAssetManagementWeEth() { + // If it succeeds, that's fine - means routing works + assertTrue(true); + } catch (bytes memory reason) { + // Verify it's not a router error (which would be "ROUTER_INVALID_SIGNATURE") + // Any other error means the router successfully routed to the pools service + string memory revertReason = string(reason); + assertFalse( + keccak256(abi.encodePacked(revertReason)) == keccak256(abi.encodePacked("ROUTER_INVALID_SIGNATURE")), + "Router should route to pools service, not return INVALID_SIGNATURE" + ); + } + } + + function testShouldRebalanceAfterProvidingLiquidity() public { + // given + address rebalancer = _getUserAddress(26); + address liquidityProvider = _getUserAddress(27); + _setupUser(liquidityProvider, 100_000 * 1e18); + + vm.prank(IporProtocolOwner); + IAmmGovernanceService(IporProtocolRouterProxy).addAppointedToRebalanceInAmm(weETH, rebalancer); + + // Provide some liquidity first + uint256 provideAmount = 100e18; + vm.prank(liquidityProvider); + IAmmPoolsServiceWeEth(IporProtocolRouterProxy).provideLiquidityWeEthToAmmPoolWeEth( + liquidityProvider, + provideAmount + ); + + uint256 treasuryBalanceBefore = IERC20(weETH).balanceOf(ammTreasuryWeEthProxy); + uint256 vaultBalanceBefore = IERC20(weETH).balanceOf(plasmaVaultWeEth); + + // when + vm.prank(rebalancer); + IAmmPoolsServiceWeEth(IporProtocolRouterProxy).rebalanceBetweenAmmTreasuryAndAssetManagementWeEth(); + + // then + uint256 treasuryBalanceAfter = IERC20(weETH).balanceOf(ammTreasuryWeEthProxy); + uint256 vaultBalanceAfter = IERC20(weETH).balanceOf(plasmaVaultWeEth); + + // With 50% ratio, balances should be approximately equal (allowing for auto-rebalance during provide) + // Total should remain the same + assertEq( + treasuryBalanceBefore + vaultBalanceBefore, + treasuryBalanceAfter + vaultBalanceAfter, + "Total balance should remain the same" + ); + + // After rebalance, they should be closer to 50/50 split + uint256 totalBalance = treasuryBalanceAfter + vaultBalanceAfter; + if (totalBalance > 0) { + // Allow some tolerance due to rounding + uint256 treasuryRatio = (treasuryBalanceAfter * 10000) / totalBalance; + assertTrue(treasuryRatio >= 4500 && treasuryRatio <= 5500, "Treasury should be around 50% of total"); + } + } +} diff --git a/test/amm-weEth/WeEthTestForkCommon.sol b/test/amm-weEth/WeEthTestForkCommon.sol index 189b9ffd5..4e41212ad 100644 --- a/test/amm-weEth/WeEthTestForkCommon.sol +++ b/test/amm-weEth/WeEthTestForkCommon.sol @@ -7,17 +7,21 @@ import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "../../contracts/tokens/IpToken.sol"; import "../../contracts/base/amm/AmmTreasuryBaseV1.sol"; +import "../../contracts/base/amm/AmmTreasuryBaseV2.sol"; import "../../contracts/base/amm/AmmStorageBaseV1.sol"; -import "../../contracts/amm-weEth/AmmPoolsServiceWeEth.sol"; -import "../../contracts/amm-weEth/AmmPoolsLensWeEth.sol"; -import "../../contracts/chains/ethereum/router/IporProtocolRouter.sol"; +import "../../contracts/chains/ethereum/amm-weEth/AmmPoolsServiceWeEth.sol"; +import "../../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; +import {AmmPoolsLensBaseV1} from "../../contracts/base/amm/services/AmmPoolsLensBaseV1.sol"; +import {IAmmGovernanceServiceBaseV1} from "../../contracts/base/interfaces/IAmmGovernanceServiceBaseV1.sol"; +import {StorageLibBaseV1} from "../../contracts/base/libraries/StorageLibBaseV1.sol"; +import "../../contracts/interfaces/IAmmGovernanceService.sol"; +import "../../contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol"; +import {MockPlasmaVault} from "../mocks/tokens/MockPlasmaVault.sol"; contract WeEthTestForkCommon is Test { - - address constant IporProtocolOwner = 0xD92E9F039E4189c342b4067CC61f5d063960D248; address payable constant IporProtocolRouterProxy = payable(0x16d104009964e694761C0bf09d7Be49B7E3C26fd); - address constant IporOracleProxy = 0x421C69EAa54646294Db30026aeE80D01988a6876; + address constant iporOracleProxy = 0x421C69EAa54646294Db30026aeE80D01988a6876; address constant AmmSwapsLens = 0x476C44E60a377C1D23877E9Dd2955C384b2DCD8c; address constant AmmPoolsLens = 0xb653ED2bBd28DF9dde734FBe85f9312151940D01; address constant AssetManagementLens = 0xB8dbDecBaF552e765619B2677f724a8415192389; @@ -40,20 +44,24 @@ contract WeEthTestForkCommon is Test { address constant ammPoolsServiceUsdm = IporProtocolRouterProxy; address constant ammPoolsLensUsdm = IporProtocolRouterProxy; - address constant eETH = 0x35fA164735182de50811E8e2E824cFb9B6118ac2; address constant weETH = 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee; address constant wETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address constant eEthLiquidityPool = 0x308861A430be4cce5502d0A12724771Fc6DaF216; address constant referral = 0x558c8eb91F6fd83FC5C995572c3515E2DAF7b7e0; + address public constant stETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; + address public constant USDM = 0x59D9356E565Ab3A36dD77763Fc0d87fEaf85508C; address ipWeEth; address ammTreasuryWeEthProxy; address ammStorageWeEthProxy; address ammPoolsLensWeEth; address ammPoolsServiceWeEth; + address plasmaVaultWeEth; + address ammPoolsLensBaseV1; + address newAmmGovernanceService; function _init() internal { vm.createSelectFork(vm.envString("ETHEREUM_PROVIDER_URL"), 19132375); @@ -61,10 +69,15 @@ contract WeEthTestForkCommon is Test { vm.startPrank(IporProtocolOwner); _createIpWeEth(); _createAmmStorageWeEth(); + _createPlasmaVaultWeEth(); _createTreasuryWeEth(); _createAmmPoolsServiceWeEth(5 * 1e15); _createAmmPoolsLensWeEth(); + _createNewAmmGovernanceService(); _updateIporRouterImplementation(); + _setupAmmGovernancePoolConfiguration(); + _setupAssetServices(); + _setupAssetLensData(); _setupPools(); vm.stopPrank(); } @@ -74,8 +87,17 @@ contract WeEthTestForkCommon is Test { IpToken(ipWeEth).setTokenManager(IporProtocolRouterProxy); } + function _createPlasmaVaultWeEth() private { + plasmaVaultWeEth = address(new MockPlasmaVault(IERC20(weETH), "ipweETHfusion", "ipweETHfusion")); + } + function _createTreasuryWeEth() private { - AmmTreasuryBaseV1 emptyImpl = new AmmTreasuryBaseV1(weETH, IporProtocolRouterProxy, ammStorageWeEthProxy); + AmmTreasuryBaseV2 emptyImpl = new AmmTreasuryBaseV2( + weETH, + IporProtocolRouterProxy, + ammStorageWeEthProxy, + plasmaVaultWeEth + ); ammTreasuryWeEthProxy = address( new ERC1967Proxy(address(emptyImpl), abi.encodeWithSignature("initialize(bool)", false)) @@ -101,55 +123,108 @@ contract WeEthTestForkCommon is Test { ipWeEthInput: ipWeEth, ammTreasuryWeEthInput: ammTreasuryWeEthProxy, ammStorageWeEthInput: ammStorageWeEthProxy, - iporOracleInput: IporOracleProxy, + ammAssetManagementInput: plasmaVaultWeEth, + iporOracleInput: iporOracleProxy, iporProtocolRouterInput: IporProtocolRouterProxy, redeemFeeRateWeEthInput: redeemFeeRateWeEthInput, eEthLiquidityPoolExternalInput: eEthLiquidityPool, - referralInput: referral + referralInput: referral, + autoRebalanceThresholdMultiplierInput: 1 // 1x for ETH-based assets }) ) ); } function _createAmmPoolsLensWeEth() private { - ammPoolsLensWeEth = address( - new AmmPoolsLensWeEth(weETH, ipWeEth, ammTreasuryWeEthProxy, ammStorageWeEthProxy, IporOracleProxy) - ); + ammPoolsLensBaseV1 = address(new AmmPoolsLensBaseV1({iporOracle_: iporOracleProxy})); + // WeETH uses ammPoolsLensBaseV1 instead of dedicated lens + ammPoolsLensWeEth = address(0); + } + + function _createNewAmmGovernanceService() private { + newAmmGovernanceService = address(new AmmGovernanceServiceBaseV1()); } function _updateIporRouterImplementation() internal { - IporProtocolRouter newImplementation = new IporProtocolRouter( - IporProtocolRouter.DeployedContracts({ + IporProtocolRouterEthereum newImplementation = new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts({ ammSwapsLens: AmmSwapsLens, ammPoolsLens: AmmPoolsLens, + ammPoolsLensBaseV1: ammPoolsLensBaseV1, assetManagementLens: AssetManagementLens, ammOpenSwapService: AmmOpenSwapService, - ammOpenSwapServiceStEth: AmmOpenSwapServiceStEth, ammCloseSwapServiceUsdt: AmmCloseSwapServiceUsdt, ammCloseSwapServiceUsdc: AmmCloseSwapServiceUsdc, ammCloseSwapServiceDai: AmmCloseSwapServiceDai, - ammCloseSwapServiceStEth: AmmCloseSwapServiceStEth, ammCloseSwapLens: AmmCloseSwapLens, ammPoolsService: AmmPoolsService, - ammGovernanceService: AmmGovernanceService, + ammGovernanceService: newAmmGovernanceService, liquidityMiningLens: LiquidityMiningLens, powerTokenLens: PowerTokenLens, flowService: FlowsService, stakeService: StakeService, - ammPoolsServiceStEth: AmmPoolsServiceEth, - ammPoolsLensStEth: AmmPoolsLensEth, - ammPoolsServiceWeEth: ammPoolsServiceWeEth, - ammPoolsLensWeEth: ammPoolsLensWeEth, - ammPoolsServiceUsdm: ammPoolsServiceUsdm, - ammPoolsLensUsdm: ammPoolsLensUsdm + stEth: stETH, + weEth: weETH, + usdm: USDM + }) + ); + + IporProtocolRouterEthereum(IporProtocolRouterProxy).upgradeTo(address(newImplementation)); + } + + function _setupAmmGovernancePoolConfiguration() private { + // Setup pool configuration for weETH with Asset Management support + IAmmGovernanceServiceBaseV1(IporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + weETH, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ + decimals: 18, + ammStorage: ammStorageWeEthProxy, + ammTreasury: ammTreasuryWeEthProxy, + ammVault: plasmaVaultWeEth, // Asset Management enabled via Plasma Vault + ammPoolsTreasury: address(0), + ammPoolsTreasuryManager: address(0), + ammCharlieTreasury: address(0), + ammCharlieTreasuryManager: address(0) }) ); + } - IporProtocolRouter(IporProtocolRouterProxy).upgradeTo(address(newImplementation)); + function _setupAssetServices() private { + // Setup AssetServices for weETH + IAmmGovernanceServiceBaseV1(IporProtocolRouterProxy).setAssetServices( + weETH, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: ammPoolsServiceWeEth, + ammOpenSwapService: address(0), + ammCloseSwapService: address(0) + }) + ); + } + + function _setupAssetLensData() private { + // Setup AssetLensData for weETH with Asset Management support + IAmmGovernanceServiceBaseV1(IporProtocolRouterProxy).setAssetLensData( + weETH, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 18, + ipToken: ipWeEth, + ammStorage: ammStorageWeEthProxy, + ammTreasury: ammTreasuryWeEthProxy, + ammVault: plasmaVaultWeEth, // Asset Management enabled via Plasma Vault + spread: address(0) // weETH doesn't have spread yet + }) + ); } function _setupPools() internal { - IAmmGovernanceService(IporProtocolRouterProxy).setAmmPoolsParams(weETH, type(uint32).max, 0, 5000); + // Set pool parameters with asset management configuration + // maxLiquidityPoolBalance: unlimited, autoRebalanceThreshold: 1 weETH, ammTreasuryAndAssetManagementRatio: 50% + IAmmGovernanceService(IporProtocolRouterProxy).setAmmPoolsParams( + weETH, + type(uint32).max, // maxLiquidityPoolBalance (unlimited) + 1, // autoRebalanceThreshold (1 weETH, will be multiplied by 1e18 * autoRebalanceThresholdMultiplier) + 5000 // ammTreasuryAndAssetManagementRatio (50%) + ); } function _setupUser(address user, uint256 value) internal { diff --git a/test/amm/AmmClosingSwaps.t.sol b/test/amm/AmmClosingSwaps.t.sol index 9738084dd..b08aad6d4 100644 --- a/test/amm/AmmClosingSwaps.t.sol +++ b/test/amm/AmmClosingSwaps.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import {DataUtils} from "../utils/DataUtils.sol"; import "../../contracts/libraries/math/IporMath.sol"; diff --git a/test/amm/AmmEvents.t.sol b/test/amm/AmmEvents.t.sol index ec20efab8..caf24d024 100644 --- a/test/amm/AmmEvents.t.sol +++ b/test/amm/AmmEvents.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/interfaces/types/AmmTypes.sol"; diff --git a/test/amm/AmmGovernanceService.t.sol b/test/amm/AmmGovernanceService.t.sol index 9b10ae8f4..3708d39e6 100644 --- a/test/amm/AmmGovernanceService.t.sol +++ b/test/amm/AmmGovernanceService.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import "../../contracts/interfaces/IAmmGovernanceLens.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; contract AmmGovernanceServiceTest is TestCommons { diff --git a/test/amm/AmmPoolsExchangeRateAndSoap.t.sol b/test/amm/AmmPoolsExchangeRateAndSoap.t.sol index 1d1bb5be4..3592f7a6b 100644 --- a/test/amm/AmmPoolsExchangeRateAndSoap.t.sol +++ b/test/amm/AmmPoolsExchangeRateAndSoap.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/amm/AmmPoolsExchangeRateLiquidity.t.sol b/test/amm/AmmPoolsExchangeRateLiquidity.t.sol index 7ccb47ec6..f87ced6c8 100644 --- a/test/amm/AmmPoolsExchangeRateLiquidity.t.sol +++ b/test/amm/AmmPoolsExchangeRateLiquidity.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../utils/DataUtils.sol"; import "../../contracts/tokens/IpToken.sol"; diff --git a/test/amm/AmmPoolsNotChangeExchangeRate.t.sol b/test/amm/AmmPoolsNotChangeExchangeRate.t.sol index 409ae4112..52f445018 100644 --- a/test/amm/AmmPoolsNotChangeExchangeRate.t.sol +++ b/test/amm/AmmPoolsNotChangeExchangeRate.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/tokens/IpToken.sol"; @@ -110,7 +110,7 @@ contract AmmPoolsNotExchangeRate is TestCommons { ); - vm.startPrank(_userTwo); + vm.startPrank(_userTwo); _iporProtocol.ammOpenSwapService.openSwapPayFixed28daysDai( _userTwo, 180 * TestConstants.D18, diff --git a/test/amm/AmmPoolsServiceNotRedeem.t.sol b/test/amm/AmmPoolsServiceNotRedeem.t.sol index bb084d074..d22b9b1a9 100644 --- a/test/amm/AmmPoolsServiceNotRedeem.t.sol +++ b/test/amm/AmmPoolsServiceNotRedeem.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/tokens/IpToken.sol"; import "../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/amm/AmmPoolsServiceOnlyRebalance.t.sol b/test/amm/AmmPoolsServiceOnlyRebalance.t.sol index 1a836c332..0fc82e4b6 100644 --- a/test/amm/AmmPoolsServiceOnlyRebalance.t.sol +++ b/test/amm/AmmPoolsServiceOnlyRebalance.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; contract AmmPoolsServiceOnlyRebalanceTest is TestCommons { IporProtocolFactory.IporProtocolConfig private _cfg; diff --git a/test/amm/AmmPoolsServiceProvideLiquidity.t.sol b/test/amm/AmmPoolsServiceProvideLiquidity.t.sol index 8434fe83b..bc56c4d9a 100644 --- a/test/amm/AmmPoolsServiceProvideLiquidity.t.sol +++ b/test/amm/AmmPoolsServiceProvideLiquidity.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/tokens/IpToken.sol"; import "../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/amm/AmmPoolsServiceProvideLiquidityAndRebalance.t.sol b/test/amm/AmmPoolsServiceProvideLiquidityAndRebalance.t.sol index 47febb664..0aa1c4d4d 100644 --- a/test/amm/AmmPoolsServiceProvideLiquidityAndRebalance.t.sol +++ b/test/amm/AmmPoolsServiceProvideLiquidityAndRebalance.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; contract AmmPoolsServiceProvideLiquidityAndRebalanceTest is TestCommons { IporProtocolFactory.IporProtocolConfig private _cfg; diff --git a/test/amm/AmmPoolsServiceRedeem.t.sol b/test/amm/AmmPoolsServiceRedeem.t.sol index dd292a410..36d2cd3cb 100644 --- a/test/amm/AmmPoolsServiceRedeem.t.sol +++ b/test/amm/AmmPoolsServiceRedeem.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/tokens/IpToken.sol"; import "../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/amm/AmmShouldClosePosition.t.sol b/test/amm/AmmShouldClosePosition.t.sol index 20882c3a8..f8b6d71be 100644 --- a/test/amm/AmmShouldClosePosition.t.sol +++ b/test/amm/AmmShouldClosePosition.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; contract AmmShouldClosePositionTest is TestCommons { diff --git a/test/amm/AmmSoap.t.sol b/test/amm/AmmSoap.t.sol index 5c19a939e..7a696ca49 100644 --- a/test/amm/AmmSoap.t.sol +++ b/test/amm/AmmSoap.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; contract AmmSoapTest is TestCommons { diff --git a/test/amm/AmmSoapAndCloseSwap.t.sol b/test/amm/AmmSoapAndCloseSwap.t.sol index 3515b5052..1bebd2493 100644 --- a/test/amm/AmmSoapAndCloseSwap.t.sol +++ b/test/amm/AmmSoapAndCloseSwap.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; contract AmmSoapAndCloseSwapTest is TestCommons { diff --git a/test/amm/AmmStorage.t.sol b/test/amm/AmmStorage.t.sol index 7b0ce0a76..8322bf57d 100644 --- a/test/amm/AmmStorage.t.sol +++ b/test/amm/AmmStorage.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/amm/AmmStorage.sol"; import "../../contracts/interfaces/types/AmmTypes.sol"; diff --git a/test/amm/AmmSwapLensOfferedRate.t.sol b/test/amm/AmmSwapLensOfferedRate.t.sol index 5cf8e1871..1ce7e2380 100644 --- a/test/amm/AmmSwapLensOfferedRate.t.sol +++ b/test/amm/AmmSwapLensOfferedRate.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; contract AmmSwapLensOfferedRateTest is TestCommons { diff --git a/test/amm/AmmTreasury.t.sol b/test/amm/AmmTreasury.t.sol index dfbed7460..c031b3c59 100644 --- a/test/amm/AmmTreasury.t.sol +++ b/test/amm/AmmTreasury.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/amm/AmmTreasury.sol"; import "../../contracts/interfaces/types/AmmTypes.sol"; diff --git a/test/amm/AmmUnwindSwap.t.sol b/test/amm/AmmUnwindSwap.t.sol index 1eece69f1..c2a089e7c 100644 --- a/test/amm/AmmUnwindSwap.t.sol +++ b/test/amm/AmmUnwindSwap.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; import "../../contracts/interfaces/types/AmmTypes.sol"; import "../../contracts/amm/AmmStorage.sol"; diff --git a/test/arbitrum/ArbitrumTestForkCommons.sol b/test/arbitrum/ArbitrumTestForkCommons.sol index 22b8b1fce..9ad90b804 100644 --- a/test/arbitrum/ArbitrumTestForkCommons.sol +++ b/test/arbitrum/ArbitrumTestForkCommons.sol @@ -9,17 +9,16 @@ import "../../contracts/oracles/IporOracle.sol"; import "../../contracts/chains/arbitrum/router/IporProtocolRouterArbitrum.sol"; import "../../contracts/interfaces/IAmmCloseSwapLens.sol"; import "../../contracts/chains/ethereum/amm-commons/AmmSwapsLens.sol"; -import "../../contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol"; -import "../../contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol"; + import "../../contracts/amm/AmmPoolsService.sol"; import "../../contracts/chains/arbitrum/amm-commons/AmmCloseSwapLensArbitrum.sol"; import "../../contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol"; import "../../contracts/chains/arbitrum/amm-commons/AmmSwapsLensArbitrum.sol"; import {StorageLibArbitrum} from "../../contracts/chains/arbitrum/libraries/StorageLibArbitrum.sol"; -import "../../contracts/chains/arbitrum/amm-wstEth/AmmPoolsServiceWstEth.sol"; import "../../contracts/base/amm/AmmStorageBaseV1.sol"; import "../../contracts/base/amm/AmmTreasuryBaseV1.sol"; +import "../../contracts/base/amm/AmmTreasuryBaseV2.sol"; import "../../contracts/base/spread/SpreadBaseV1.sol"; import "../../contracts/tokens/IpToken.sol"; @@ -27,6 +26,10 @@ import "./interfaces/IERC20Bridged.sol"; import {AmmPoolsLensArbitrum} from "../../contracts/chains/arbitrum/amm-commons/AmmPoolsLensArbitrum.sol"; import {AmmPoolsServiceUsdm} from "../../contracts/amm-usdm/AmmPoolsServiceUsdm.sol"; +import {AmmPoolsServiceWstEth} from "../../contracts/chains/arbitrum/amm-wstEth/AmmPoolsServiceWstEth.sol"; +import {AmmCloseSwapServiceWstEthBaseV2} from "../../contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV2.sol"; +import {AmmOpenSwapServiceWstEthBaseV1} from "../../contracts/base/amm-wstEth/services/AmmOpenSwapServiceWstEthBaseV1.sol"; +import {MockPlasmaVault} from "../mocks/tokens/MockPlasmaVault.sol"; contract ArbitrumTestForkCommons is Test { address internal constant WST_ETH_BRIDGE = 0x07D4692291B9E30E326fd31706f686f83f331B82; @@ -86,6 +89,8 @@ contract ArbitrumTestForkCommons is Test { address public iporOracleImpl; address public iporOracleProxy; + address public newPlasmaVaultWstEth; + function _init() internal { messageSignerPrivateKey = 0x12341234; messageSignerAddress = vm.addr(messageSignerPrivateKey); @@ -94,16 +99,18 @@ contract ArbitrumTestForkCommons is Test { _createIpToken(); _createIporOracle(); _createAmmStorage(); - _createSpreadForWstEth(); - _upgradeAmmTreasury(); + _createPlasmaVaults(); + _upgradeAmmTreasury(); _createAmmSwapsLens(); _createAmmPoolsLens(); _createAmmCloseSwapLens(); _createGovernanceService(); + _createSpreadForWstEth(); + _createAmmPoolsServices(); _createAmmOpenSwapServiceWstEth(); _createAmmCloseSwapServiceWstEth(); @@ -119,77 +126,87 @@ contract ArbitrumTestForkCommons is Test { vm.stopPrank(); } + function _createPlasmaVaults() internal { + newPlasmaVaultWstEth = address(new MockPlasmaVault(IERC20(wstETH), "ipwstETHfusion", "ipwstETHfusion")); + } + function _setupIporProtocol() internal { address[] memory guardians = new address[](1); guardians[0] = owner; - AmmTreasuryBaseV1(ammTreasuryWstEthProxy).addPauseGuardians(guardians); - AmmTreasuryBaseV1(ammTreasuryWstEthProxy).unpause(); + AmmTreasuryBaseV2(ammTreasuryWstEthProxy).addPauseGuardians(guardians); + AmmTreasuryBaseV2(ammTreasuryWstEthProxy).unpause(); IAmmGovernanceService(iporProtocolRouterProxy).setAmmPoolsParams(wstETH, 1000000000, 0, 0); IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setMessageSigner(messageSignerAddress); - IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration(wstETH, StorageLibArbitrum.AssetGovernancePoolConfigValue({ - decimals: IERC20MetadataUpgradeable(wstETH).decimals(), - ammStorage: ammStorageWstEthProxy, - ammTreasury: ammTreasuryWstEthProxy, - ammVault: address(0), - ammPoolsTreasury: treasurer, - ammPoolsTreasuryManager: treasurer, - ammCharlieTreasury: treasurer, - ammCharlieTreasuryManager: treasurer - } - )); - - IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAssetLensData(wstETH, StorageLibArbitrum.AssetLensDataValue({ - decimals: IERC20MetadataUpgradeable(wstETH).decimals(), - ipToken: ipwstETH, - ammStorage: ammStorageWstEthProxy, - ammTreasury: ammTreasuryWstEthProxy, - ammVault: address(0), - spread: spreadWstEth - })); - - IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAssetServices(wstETH, StorageLibArbitrum.AssetServicesValue({ - ammPoolsService: ammPoolsServiceWstEth, - ammOpenSwapService: ammOpenSwapServiceWstEth, - ammCloseSwapService: ammCloseSwapServiceWstEth - })); + IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + wstETH, + StorageLibArbitrum.AssetGovernancePoolConfigValue({ + decimals: IERC20MetadataUpgradeable(wstETH).decimals(), + ammStorage: ammStorageWstEthProxy, + ammTreasury: ammTreasuryWstEthProxy, + ammVault: address(0), + ammPoolsTreasury: treasurer, + ammPoolsTreasuryManager: treasurer, + ammCharlieTreasury: treasurer, + ammCharlieTreasuryManager: treasurer + }) + ); + + IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAssetLensData( + wstETH, + StorageLibArbitrum.AssetLensDataValue({ + decimals: IERC20MetadataUpgradeable(wstETH).decimals(), + ipToken: ipwstETH, + ammStorage: ammStorageWstEthProxy, + ammTreasury: ammTreasuryWstEthProxy, + ammVault: address(0), + spread: spreadWstEth + }) + ); + IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAssetServices( + wstETH, + StorageLibArbitrum.AssetServicesValue({ + ammPoolsService: ammPoolsServiceWstEth, + ammOpenSwapService: ammOpenSwapServiceWstEth, + ammCloseSwapService: ammCloseSwapServiceWstEth + }) + ); } function _setupAssetServices() internal { - IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAssetServices(wstETH, StorageLibArbitrum.AssetServicesValue({ - ammPoolsService: ammPoolsServiceWstEth, - ammOpenSwapService: ammOpenSwapServiceWstEth, - ammCloseSwapService: ammCloseSwapServiceWstEth - })); + IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAssetServices( + wstETH, + StorageLibArbitrum.AssetServicesValue({ + ammPoolsService: ammPoolsServiceWstEth, + ammOpenSwapService: ammOpenSwapServiceWstEth, + ammCloseSwapService: ammCloseSwapServiceWstEth + }) + ); } function _createGovernanceService() internal { - ammGovernanceService = address( - new AmmGovernanceServiceArbitrum() - ); + ammGovernanceService = address(new AmmGovernanceServiceArbitrum()); } function _createDummyContracts() internal { IporProtocolRouterArbitrum.DeployedContractsArbitrum memory deployedContracts = IporProtocolRouterArbitrum .DeployedContractsArbitrum({ - ammSwapsLens: _defaultAddress, - ammPoolsLens: _defaultAddress, - ammCloseSwapLens: _defaultAddress, - ammGovernanceService: _defaultAddress, - - liquidityMiningLens: _defaultAddress, - powerTokenLens: _defaultAddress, - flowService: _defaultAddress, - stakeService: _defaultAddress, - - wstEth: wstETH, - usdc: USDC, - usdm: USDM - }); + ammSwapsLens: _defaultAddress, + ammPoolsLens: _defaultAddress, + ammCloseSwapLens: _defaultAddress, + ammGovernanceService: _defaultAddress, + liquidityMiningLens: _defaultAddress, + powerTokenLens: _defaultAddress, + flowService: _defaultAddress, + stakeService: _defaultAddress, + wstEth: wstETH, + usdc: USDC, + usdm: USDM + }); iporProtocolRouterImpl = address(new IporProtocolRouterArbitrum(deployedContracts)); @@ -229,20 +246,18 @@ contract ArbitrumTestForkCommons is Test { function _updateIporRouterImplementation() internal { IporProtocolRouterArbitrum.DeployedContractsArbitrum memory deployedContracts = IporProtocolRouterArbitrum .DeployedContractsArbitrum({ - ammSwapsLens: ammSwapsLens, - ammPoolsLens: ammPoolsLens, - ammCloseSwapLens: ammCloseSwapLens, - ammGovernanceService: ammGovernanceService, - - liquidityMiningLens: _defaultAddress, - powerTokenLens: _defaultAddress, - flowService: _defaultAddress, - stakeService: _defaultAddress, - - wstEth: wstETH, - usdc: USDC, - usdm: USDM - }); + ammSwapsLens: ammSwapsLens, + ammPoolsLens: ammPoolsLens, + ammCloseSwapLens: ammCloseSwapLens, + ammGovernanceService: ammGovernanceService, + liquidityMiningLens: _defaultAddress, + powerTokenLens: _defaultAddress, + flowService: _defaultAddress, + stakeService: _defaultAddress, + wstEth: wstETH, + usdc: USDC, + usdm: USDM + }); iporProtocolRouterImpl = address(new IporProtocolRouterArbitrum(deployedContracts)); @@ -254,15 +269,11 @@ contract ArbitrumTestForkCommons is Test { } function _createAmmSwapsLens() private { - ammSwapsLens = address( - new AmmSwapsLensArbitrum(iporOracleProxy) - ); + ammSwapsLens = address(new AmmSwapsLensArbitrum(iporOracleProxy)); } function _createAmmPoolsLens() private { - ammPoolsLens = address( - new AmmPoolsLensArbitrum(iporOracleProxy) - ); + ammPoolsLens = address(new AmmPoolsLensArbitrum(iporOracleProxy)); } function _createAmmPoolsServices() private { @@ -272,9 +283,11 @@ contract ArbitrumTestForkCommons is Test { ipwstEthInput: ipwstETH, ammTreasuryWstEthInput: ammTreasuryWstEthProxy, ammStorageWstEthInput: ammStorageWstEthProxy, + ammAssetManagementInput: newPlasmaVaultWstEth, iporOracleInput: iporOracleProxy, iporProtocolRouterInput: iporProtocolRouterProxy, - redeemFeeRateWstEthInput: 5 * 1e15 + redeemFeeRateWstEthInput: 5 * 1e15, + autoRebalanceThresholdMultiplier_: 1 }) ); @@ -298,16 +311,20 @@ contract ArbitrumTestForkCommons is Test { ipwstEthInput: ipwstETH, ammTreasuryWstEthInput: ammTreasuryWstEthProxy, ammStorageWstEthInput: ammStorageWstEthProxy, + ammAssetManagementInput: newPlasmaVaultWstEth, iporOracleInput: iporOracleProxy, iporProtocolRouterInput: iporProtocolRouterProxy, - redeemFeeRateWstEthInput: 0 + redeemFeeRateWstEthInput: 0, + autoRebalanceThresholdMultiplier_: 1 }) ); } function _upgradeAmmTreasury() private { - ammTreasuryWstEthImpl = address(new AmmTreasuryBaseV1(wstETH, iporProtocolRouterProxy, ammStorageWstEthProxy)); - AmmTreasuryBaseV1(ammTreasuryWstEthProxy).upgradeTo(ammTreasuryWstEthImpl); + ammTreasuryWstEthImpl = address( + new AmmTreasuryBaseV2(wstETH, iporProtocolRouterProxy, ammStorageWstEthProxy, newPlasmaVaultWstEth) + ); + AmmTreasuryBaseV2(ammTreasuryWstEthProxy).upgradeTo(ammTreasuryWstEthImpl); ammTreasuryUsdmImpl = address(new AmmTreasuryBaseV1(USDM, iporProtocolRouterProxy, ammStorageUsdmProxy)); AmmTreasuryBaseV1(ammTreasuryUsdmProxy).upgradeTo(ammTreasuryUsdmImpl); } @@ -327,20 +344,20 @@ contract ArbitrumTestForkCommons is Test { function _createAmmOpenSwapServiceWstEth() private { ammOpenSwapServiceWstEth = address( - new AmmOpenSwapServiceWstEth({ + new AmmOpenSwapServiceWstEthBaseV1({ poolCfg: AmmTypesBaseV1.AmmOpenSwapServicePoolConfiguration({ - asset: wstETH, - decimals: IERC20MetadataUpgradeable(wstETH).decimals(), - ammStorage: ammStorageWstEthProxy, - ammTreasury: ammTreasuryWstEthProxy, - spread: spreadWstEth, - iporPublicationFee: 10 * 1e15, - maxSwapCollateralAmount: 100_000 * 1e18, - liquidationDepositAmount: 1000, - minLeverage: 10 * 1e18, - openingFeeRate: 5e14, - openingFeeTreasuryPortionRate: 5e17 - }), + asset: wstETH, + decimals: IERC20MetadataUpgradeable(wstETH).decimals(), + ammStorage: ammStorageWstEthProxy, + ammTreasury: ammTreasuryWstEthProxy, + spread: spreadWstEth, + iporPublicationFee: 10 * 1e15, + maxSwapCollateralAmount: 100_000 * 1e18, + liquidationDepositAmount: 1000, + minLeverage: 10 * 1e18, + openingFeeRate: 5e14, + openingFeeTreasuryPortionRate: 5e17 + }), iporOracle_: iporOracleProxy }) ); @@ -349,20 +366,20 @@ contract ArbitrumTestForkCommons is Test { /// @dev case where liquidationDepositAmount is 0 and openingFeeRate is 0 function _createAmmOpenSwapServiceWstEthCase2() internal { ammOpenSwapServiceWstEth = address( - new AmmOpenSwapServiceWstEth({ + new AmmOpenSwapServiceWstEthBaseV1({ poolCfg: AmmTypesBaseV1.AmmOpenSwapServicePoolConfiguration({ - asset: wstETH, - decimals: IERC20MetadataUpgradeable(wstETH).decimals(), - ammStorage: ammStorageWstEthProxy, - ammTreasury: ammTreasuryWstEthProxy, - spread: spreadWstEth, - iporPublicationFee: 5 * 1e15, - maxSwapCollateralAmount: 50 * 1e18, - liquidationDepositAmount: 0, - minLeverage: 10 * 1e18, - openingFeeRate: 0, - openingFeeTreasuryPortionRate: 5e17 - }), + asset: wstETH, + decimals: IERC20MetadataUpgradeable(wstETH).decimals(), + ammStorage: ammStorageWstEthProxy, + ammTreasury: ammTreasuryWstEthProxy, + spread: spreadWstEth, + iporPublicationFee: 5 * 1e15, + maxSwapCollateralAmount: 50 * 1e18, + liquidationDepositAmount: 0, + minLeverage: 10 * 1e18, + openingFeeRate: 0, + openingFeeTreasuryPortionRate: 5e17 + }), iporOracle_: iporOracleProxy }) ); @@ -371,55 +388,53 @@ contract ArbitrumTestForkCommons is Test { /// @dev case where liquidationDepositAmount openingFeeRate is 0 function _createAmmOpenSwapServiceWstEthCase3() internal { ammOpenSwapServiceWstEth = address( - new AmmOpenSwapServiceWstEth({ + new AmmOpenSwapServiceWstEthBaseV1({ poolCfg: AmmTypesBaseV1.AmmOpenSwapServicePoolConfiguration({ - asset: wstETH, - decimals: IERC20MetadataUpgradeable(wstETH).decimals(), - ammStorage: ammStorageWstEthProxy, - ammTreasury: ammTreasuryWstEthProxy, - spread: spreadWstEth, - iporPublicationFee: 5 * 1e15, - maxSwapCollateralAmount: 50 * 1e18, - liquidationDepositAmount: 10000, - minLeverage: 10 * 1e18, - openingFeeRate: 0, - openingFeeTreasuryPortionRate: 5e17 - }), + asset: wstETH, + decimals: IERC20MetadataUpgradeable(wstETH).decimals(), + ammStorage: ammStorageWstEthProxy, + ammTreasury: ammTreasuryWstEthProxy, + spread: spreadWstEth, + iporPublicationFee: 5 * 1e15, + maxSwapCollateralAmount: 50 * 1e18, + liquidationDepositAmount: 10000, + minLeverage: 10 * 1e18, + openingFeeRate: 0, + openingFeeTreasuryPortionRate: 5e17 + }), iporOracle_: iporOracleProxy }) ); } function _createAmmCloseSwapLens() private { - ammCloseSwapLens = address( - new AmmCloseSwapLensArbitrum(iporOracleProxy) - ); + ammCloseSwapLens = address(new AmmCloseSwapLensArbitrum(iporOracleProxy)); } function _createAmmCloseSwapServiceWstEth() private { ammCloseSwapServiceWstEth = address( - new AmmCloseSwapServiceWstEth({ + new AmmCloseSwapServiceWstEthBaseV2({ poolCfg: IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration({ - asset: wstETH, - decimals: IERC20MetadataUpgradeable(wstETH).decimals(), - ammStorage: ammStorageWstEthProxy, - ammTreasury: ammTreasuryWstEthProxy, - assetManagement: address(0), - spread: spreadWstEth, - unwindingFeeTreasuryPortionRate: 25e16, - unwindingFeeRate: 5 * 1e11, - maxLengthOfLiquidatedSwapsPerLeg: 10, - timeBeforeMaturityAllowedToCloseSwapByCommunity: 1 hours, - timeBeforeMaturityAllowedToCloseSwapByBuyerTenor28days: 1 days, - timeBeforeMaturityAllowedToCloseSwapByBuyerTenor60days: 2 days, - timeBeforeMaturityAllowedToCloseSwapByBuyerTenor90days: 3 days, - minLiquidationThresholdToCloseBeforeMaturityByCommunity: 995 * 1e15, - minLiquidationThresholdToCloseBeforeMaturityByBuyer: 99 * 1e16, - minLeverage: 10 * 1e18, - timeAfterOpenAllowedToCloseSwapWithUnwindingTenor28days: 1 days, - timeAfterOpenAllowedToCloseSwapWithUnwindingTenor60days: 2 days, - timeAfterOpenAllowedToCloseSwapWithUnwindingTenor90days: 3 days - }), + asset: wstETH, + decimals: IERC20MetadataUpgradeable(wstETH).decimals(), + ammStorage: ammStorageWstEthProxy, + ammTreasury: ammTreasuryWstEthProxy, + assetManagement: newPlasmaVaultWstEth, + spread: spreadWstEth, + unwindingFeeTreasuryPortionRate: 25e16, + unwindingFeeRate: 5 * 1e11, + maxLengthOfLiquidatedSwapsPerLeg: 10, + timeBeforeMaturityAllowedToCloseSwapByCommunity: 1 hours, + timeBeforeMaturityAllowedToCloseSwapByBuyerTenor28days: 1 days, + timeBeforeMaturityAllowedToCloseSwapByBuyerTenor60days: 2 days, + timeBeforeMaturityAllowedToCloseSwapByBuyerTenor90days: 3 days, + minLiquidationThresholdToCloseBeforeMaturityByCommunity: 995 * 1e15, + minLiquidationThresholdToCloseBeforeMaturityByBuyer: 99 * 1e16, + minLeverage: 10 * 1e18, + timeAfterOpenAllowedToCloseSwapWithUnwindingTenor28days: 1 days, + timeAfterOpenAllowedToCloseSwapWithUnwindingTenor60days: 2 days, + timeAfterOpenAllowedToCloseSwapWithUnwindingTenor90days: 3 days + }), iporOracle_: iporOracleProxy }) ); @@ -427,28 +442,28 @@ contract ArbitrumTestForkCommons is Test { function _createAmmCloseSwapServiceStEthUnwindCase1() internal { ammCloseSwapServiceWstEth = address( - new AmmCloseSwapServiceWstEth({ + new AmmCloseSwapServiceWstEthBaseV2({ poolCfg: IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration({ - asset: wstETH, - decimals: IERC20MetadataUpgradeable(wstETH).decimals(), - ammStorage: ammStorageWstEthProxy, - ammTreasury: ammTreasuryWstEthProxy, - assetManagement: address(0), - spread: spreadWstEth, - unwindingFeeTreasuryPortionRate: 5 * 1e17, - unwindingFeeRate: 5 * 1e14, - maxLengthOfLiquidatedSwapsPerLeg: 10, - timeBeforeMaturityAllowedToCloseSwapByCommunity: 1 hours, - timeBeforeMaturityAllowedToCloseSwapByBuyerTenor28days: 1 days, - timeBeforeMaturityAllowedToCloseSwapByBuyerTenor60days: 3 days, - timeBeforeMaturityAllowedToCloseSwapByBuyerTenor90days: 3 days, - minLiquidationThresholdToCloseBeforeMaturityByCommunity: 995 * 1e15, - minLiquidationThresholdToCloseBeforeMaturityByBuyer: 99 * 1e16, - minLeverage: 10 * 1e18, - timeAfterOpenAllowedToCloseSwapWithUnwindingTenor28days: 1 days, - timeAfterOpenAllowedToCloseSwapWithUnwindingTenor60days: 60 days, - timeAfterOpenAllowedToCloseSwapWithUnwindingTenor90days: 90 days - }), + asset: wstETH, + decimals: IERC20MetadataUpgradeable(wstETH).decimals(), + ammStorage: ammStorageWstEthProxy, + ammTreasury: ammTreasuryWstEthProxy, + assetManagement: newPlasmaVaultWstEth, + spread: spreadWstEth, + unwindingFeeTreasuryPortionRate: 5 * 1e17, + unwindingFeeRate: 5 * 1e14, + maxLengthOfLiquidatedSwapsPerLeg: 10, + timeBeforeMaturityAllowedToCloseSwapByCommunity: 1 hours, + timeBeforeMaturityAllowedToCloseSwapByBuyerTenor28days: 1 days, + timeBeforeMaturityAllowedToCloseSwapByBuyerTenor60days: 3 days, + timeBeforeMaturityAllowedToCloseSwapByBuyerTenor90days: 3 days, + minLiquidationThresholdToCloseBeforeMaturityByCommunity: 995 * 1e15, + minLiquidationThresholdToCloseBeforeMaturityByBuyer: 99 * 1e16, + minLeverage: 10 * 1e18, + timeAfterOpenAllowedToCloseSwapWithUnwindingTenor28days: 1 days, + timeAfterOpenAllowedToCloseSwapWithUnwindingTenor60days: 60 days, + timeAfterOpenAllowedToCloseSwapWithUnwindingTenor90days: 90 days + }), iporOracle_: iporOracleProxy }) ); @@ -456,7 +471,7 @@ contract ArbitrumTestForkCommons is Test { function _createSpreadForWstEth() private { SpreadTypesBaseV1.TimeWeightedNotionalMemory[] - memory timeWeightedNotionals = new SpreadTypesBaseV1.TimeWeightedNotionalMemory[](3); + memory timeWeightedNotionals = new SpreadTypesBaseV1.TimeWeightedNotionalMemory[](3); timeWeightedNotionals[0].storageId = SpreadStorageLibsBaseV1.StorageId.TimeWeightedNotional28Days; timeWeightedNotionals[1].storageId = SpreadStorageLibsBaseV1.StorageId.TimeWeightedNotional60Days; diff --git a/test/arbitrum/usdc/ArbitrumForkAmmUsdcRebalance.t.sol b/test/arbitrum/usdc/ArbitrumForkAmmUsdcRebalance.t.sol new file mode 100644 index 000000000..6b6864ed3 --- /dev/null +++ b/test/arbitrum/usdc/ArbitrumForkAmmUsdcRebalance.t.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import "./UsdcTestForkCommonArbitrum.sol"; +import {IAmmPoolsServiceUsdcBaseV1} from "../../../contracts/base/amm-usdc/interfaces/IAmmPoolsServiceUsdcBaseV1.sol"; +import {IAmmGovernanceService} from "../../../contracts/interfaces/IAmmGovernanceService.sol"; +import {IAmmGovernanceLens} from "../../../contracts/interfaces/IAmmGovernanceLens.sol"; +import {AmmPoolsErrors} from "../../../contracts/libraries/errors/AmmPoolsErrors.sol"; +import {IAmmGovernanceServiceArbitrum} from "../../../contracts/chains/arbitrum/interfaces/IAmmGovernanceServiceArbitrum.sol"; +import {StorageLibArbitrum} from "../../../contracts/chains/arbitrum/libraries/StorageLibArbitrum.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +/// @title Simple tests for rebalanceBetweenAmmTreasuryAndAssetManagementUsdc router integration +/// @notice These tests verify that the router properly routes the rebalance function +contract ArbitrumForkAmmUsdcRebalanceTest is UsdcTestForkCommonArbitrum { + function setUp() public { + _init(); + _setupAssetManagement(); + } + + function _setupAssetManagement() internal { + vm.startPrank(PROTOCOL_OWNER); + + // Configure governance pool with asset management (ammVault) enabled + IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + USDC, + StorageLibArbitrum.AssetGovernancePoolConfigValue({ + decimals: IERC20Metadata(USDC).decimals(), + ammStorage: ammStorageUsdcProxy, + ammTreasury: ammTreasuryUsdcProxy, + ammVault: ammAssetManagementUsdc, // Set to plasma vault instead of address(0) + ammPoolsTreasury: treasurer, + ammPoolsTreasuryManager: treasurer, + ammCharlieTreasury: treasurer, + ammCharlieTreasuryManager: treasurer + }) + ); + + // Set proper AMM pools params with asset management ratio + IAmmGovernanceService(iporProtocolRouterProxy).setAmmPoolsParams( + USDC, + 1000000000, // maxLiquidityPoolBalance + 1, // autoRebalanceThreshold + 5000 // ammTreasuryAndAssetManagementRatio (50%) + ); + + vm.stopPrank(); + } + + function testShouldRevertWhenNotAppointedToRebalanceUsdc() public { + // given + address user = _getUserAddress(22); + + // when & then + vm.expectRevert(bytes(AmmPoolsErrors.CALLER_NOT_APPOINTED_TO_REBALANCE)); + vm.prank(user); + IAmmPoolsServiceUsdcBaseV1(iporProtocolRouterProxy).rebalanceBetweenAmmTreasuryAndAssetManagementUsdc(); + } + + function testShouldAddUserToAppointedRebalanceUsdc() public { + // given + address user = _getUserAddress(23); + + bool isAppointedBefore = IAmmGovernanceLens(iporProtocolRouterProxy).isAppointedToRebalanceInAmm(USDC, user); + + // when + vm.prank(PROTOCOL_OWNER); + IAmmGovernanceService(iporProtocolRouterProxy).addAppointedToRebalanceInAmm(USDC, user); + + // then + bool isAppointedAfter = IAmmGovernanceLens(iporProtocolRouterProxy).isAppointedToRebalanceInAmm(USDC, user); + assertFalse(isAppointedBefore, "User should not be appointed before"); + assertTrue(isAppointedAfter, "User should be appointed after"); + } + + function testShouldRemoveUserFromAppointedRebalanceUsdc() public { + // given + address user = _getUserAddress(24); + + vm.prank(PROTOCOL_OWNER); + IAmmGovernanceService(iporProtocolRouterProxy).addAppointedToRebalanceInAmm(USDC, user); + + bool isAppointedBefore = IAmmGovernanceLens(iporProtocolRouterProxy).isAppointedToRebalanceInAmm(USDC, user); + + // when + vm.prank(PROTOCOL_OWNER); + IAmmGovernanceService(iporProtocolRouterProxy).removeAppointedToRebalanceInAmm(USDC, user); + + // then + bool isAppointedAfter = IAmmGovernanceLens(iporProtocolRouterProxy).isAppointedToRebalanceInAmm(USDC, user); + assertTrue(isAppointedBefore, "User should be appointed before"); + assertFalse(isAppointedAfter, "User should not be appointed after"); + } + + function testShouldCallRebalanceFunctionThroughRouter() public { + // given + address user = _getUserAddress(25); + vm.prank(PROTOCOL_OWNER); + IAmmGovernanceService(iporProtocolRouterProxy).addAppointedToRebalanceInAmm(USDC, user); + + // when & then + // This test verifies that the router correctly routes to the rebalance function + // The function will revert during actual execution due to mock setup limitations, + // but we can verify it reaches the correct contract by checking the revert doesn't + // come from the router's INVALID_SIGNATURE error + vm.prank(user); + try + IAmmPoolsServiceUsdcBaseV1(iporProtocolRouterProxy).rebalanceBetweenAmmTreasuryAndAssetManagementUsdc() + { + // If it succeeds, that's also fine - means routing works + assertTrue(true); + } catch (bytes memory reason) { + // Verify it's not a router error (which would be "ROUTER_INVALID_SIGNATURE") + // Any other error means the router successfully routed to the pools service + string memory revertReason = string(reason); + assertFalse( + keccak256(abi.encodePacked(revertReason)) == keccak256(abi.encodePacked("ROUTER_INVALID_SIGNATURE")), + "Router should route to pools service, not return INVALID_SIGNATURE" + ); + } + } +} + diff --git a/test/arbitrum/usdc/UsdcTestForkCommonArbitrum.sol b/test/arbitrum/usdc/UsdcTestForkCommonArbitrum.sol index 686684791..4f6ab3cc5 100644 --- a/test/arbitrum/usdc/UsdcTestForkCommonArbitrum.sol +++ b/test/arbitrum/usdc/UsdcTestForkCommonArbitrum.sol @@ -12,14 +12,11 @@ import "../../../contracts/interfaces/IAmmCloseSwapLens.sol"; import "../../../contracts/chains/ethereum/amm-commons/AmmSwapsLens.sol"; import "../../../contracts/amm/AmmPoolsLens.sol"; import "../../../contracts/amm/AssetManagementLens.sol"; -import "../../../contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol"; -import "../../../contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol"; import "../../../contracts/amm/AmmPoolsService.sol"; import "../../../contracts/chains/arbitrum/amm-commons/AmmCloseSwapLensArbitrum.sol"; import "../../../contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol"; import "../../../contracts/chains/arbitrum/amm-commons/AmmSwapsLensArbitrum.sol"; -import "../../../contracts/chains/arbitrum/amm-wstEth/AmmPoolsServiceWstEth.sol"; import "../../../contracts/base/amm/AmmStorageBaseV1.sol"; import "../../../contracts/base/amm/AmmTreasuryBaseV2.sol"; import "../../../contracts/base/spread/SpreadBaseV1.sol"; @@ -27,11 +24,10 @@ import "../../../contracts/base/spread/SpreadBaseV1.sol"; import "../../../contracts/tokens/IpToken.sol"; import "../../arbitrum/interfaces/IERC20Bridged.sol"; import {AmmPoolsLensArbitrum} from "../../../contracts/chains/arbitrum/amm-commons/AmmPoolsLensArbitrum.sol"; -import {AmmPoolsServiceUsdc} from "../../../contracts/chains/arbitrum/amm-usdc/AmmPoolsServiceUsdc.sol"; +import {AmmPoolsServiceUsdcBaseV1} from "../../../contracts/base/amm-usdc/services/AmmPoolsServiceUsdcBaseV1.sol"; import {IAmmPoolsServiceUsdc} from "../../../contracts/chains/arbitrum/interfaces/IAmmPoolsServiceUsdc.sol"; import {AmmOpenSwapServiceUsdc} from "../../../contracts/chains/arbitrum/amm-usdc/AmmOpenSwapServiceUsdc.sol"; import {AmmCloseSwapServiceUsdc} from "../../../contracts/chains/arbitrum/amm-usdc/AmmCloseSwapServiceUsdc.sol"; -import "../../../contracts/amm-usdm/AmmPoolsServiceUsdm.sol"; import {MockPlasmaVault} from "../../mocks/tokens/MockPlasmaVault.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; @@ -342,7 +338,7 @@ contract UsdcTestForkCommonArbitrum is Test { function _createAmmPoolsServiceUsdc() private { ammPoolsServiceUsdc = address( - new AmmPoolsServiceUsdc( + new AmmPoolsServiceUsdcBaseV1( { asset_: USDC, ipToken_: ipUsdc, @@ -376,7 +372,7 @@ contract UsdcTestForkCommonArbitrum is Test { function _createAmmPoolsServiceUsdc(uint redeemFeeRateAssetInput) internal { ammPoolsServiceUsdc = address( - new AmmPoolsServiceUsdc( + new AmmPoolsServiceUsdcBaseV1( { asset_: USDC, ipToken_: ipUsdc, @@ -394,7 +390,7 @@ contract UsdcTestForkCommonArbitrum is Test { function _createNewAmmPoolsServiceUsdcWithZEROFee() internal { ammPoolsServiceUsdc = address( - new AmmPoolsServiceUsdc({ + new AmmPoolsServiceUsdcBaseV1({ asset_: USDC, ipToken_: ipUsdc, ammTreasury_: ammTreasuryUsdcProxy, diff --git a/test/arbitrum/wstETH/ArbitrumForkAmmWstEthRebalance.t.sol b/test/arbitrum/wstETH/ArbitrumForkAmmWstEthRebalance.t.sol new file mode 100644 index 000000000..7125e4a5a --- /dev/null +++ b/test/arbitrum/wstETH/ArbitrumForkAmmWstEthRebalance.t.sol @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.26; + +import "../ArbitrumTestForkCommons.sol"; +import {IAmmPoolsServiceWstEthBaseV2} from "../../../contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol"; +import {IAmmGovernanceService} from "../../../contracts/interfaces/IAmmGovernanceService.sol"; +import {IAmmGovernanceLens} from "../../../contracts/interfaces/IAmmGovernanceLens.sol"; +import {AmmPoolsErrors} from "../../../contracts/libraries/errors/AmmPoolsErrors.sol"; +import {IAmmGovernanceServiceArbitrum} from "../../../contracts/chains/arbitrum/interfaces/IAmmGovernanceServiceArbitrum.sol"; +import {StorageLibArbitrum} from "../../../contracts/chains/arbitrum/libraries/StorageLibArbitrum.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +/// @title Simple tests for rebalanceBetweenAmmTreasuryAndAssetManagementWstEth router integration +/// @notice These tests verify that the router properly routes the rebalance function +contract ArbitrumForkAmmWstEthRebalanceTest is ArbitrumTestForkCommons { + function setUp() public { + vm.createSelectFork(vm.envString("ARBITRUM_PROVIDER_URL"), 171764768); + _init(); + _setupAssetManagement(); + } + + function _setupAssetManagement() internal { + // Configure governance pool with asset management (ammVault) enabled + IAmmGovernanceServiceArbitrum(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + wstETH, + StorageLibArbitrum.AssetGovernancePoolConfigValue({ + decimals: IERC20Metadata(wstETH).decimals(), + ammStorage: ammStorageWstEthProxy, + ammTreasury: ammTreasuryWstEthProxy, + ammVault: newPlasmaVaultWstEth, // Set to plasma vault instead of address(0) + ammPoolsTreasury: treasurer, + ammPoolsTreasuryManager: treasurer, + ammCharlieTreasury: treasurer, + ammCharlieTreasuryManager: treasurer + }) + ); + + // Set proper AMM pools params with asset management ratio + IAmmGovernanceService(iporProtocolRouterProxy).setAmmPoolsParams( + wstETH, + 1000000000, // maxLiquidityPoolBalance + 1, // autoRebalanceThreshold + 5000 // ammTreasuryAndAssetManagementRatio (50%) + ); + } + + function testShouldRevertWhenNotAppointedToRebalanceWstEth() public { + // given + address user = _getUserAddress(22); + + // when & then + vm.expectRevert(bytes(AmmPoolsErrors.CALLER_NOT_APPOINTED_TO_REBALANCE)); + vm.prank(user); + IAmmPoolsServiceWstEthBaseV2(iporProtocolRouterProxy).rebalanceBetweenAmmTreasuryAndAssetManagementWstEth(); + } + + function testShouldAddUserToAppointedRebalanceWstEth() public { + // given + address user = _getUserAddress(23); + + bool isAppointedBefore = IAmmGovernanceLens(iporProtocolRouterProxy).isAppointedToRebalanceInAmm(wstETH, user); + + // when + IAmmGovernanceService(iporProtocolRouterProxy).addAppointedToRebalanceInAmm(wstETH, user); + + // then + bool isAppointedAfter = IAmmGovernanceLens(iporProtocolRouterProxy).isAppointedToRebalanceInAmm(wstETH, user); + assertFalse(isAppointedBefore, "User should not be appointed before"); + assertTrue(isAppointedAfter, "User should be appointed after"); + } + + function testShouldRemoveUserFromAppointedRebalanceWstEth() public { + // given + address user = _getUserAddress(24); + + IAmmGovernanceService(iporProtocolRouterProxy).addAppointedToRebalanceInAmm(wstETH, user); + + bool isAppointedBefore = IAmmGovernanceLens(iporProtocolRouterProxy).isAppointedToRebalanceInAmm(wstETH, user); + + // when + IAmmGovernanceService(iporProtocolRouterProxy).removeAppointedToRebalanceInAmm(wstETH, user); + + // then + bool isAppointedAfter = IAmmGovernanceLens(iporProtocolRouterProxy).isAppointedToRebalanceInAmm(wstETH, user); + assertTrue(isAppointedBefore, "User should be appointed before"); + assertFalse(isAppointedAfter, "User should not be appointed after"); + } + + function testShouldCallRebalanceFunctionThroughRouter() public { + // given + address user = _getUserAddress(25); + IAmmGovernanceService(iporProtocolRouterProxy).addAppointedToRebalanceInAmm(wstETH, user); + + // when & then + // This test verifies that the router correctly routes to the rebalance function + // The function will revert during actual execution due to mock setup limitations, + // but we can verify it reaches the correct contract by checking the revert doesn't + // come from the router's INVALID_SIGNATURE error + vm.prank(user); + try + IAmmPoolsServiceWstEthBaseV2(iporProtocolRouterProxy).rebalanceBetweenAmmTreasuryAndAssetManagementWstEth() + { + // If it succeeds, that's also fine - means routing works + assertTrue(true); + } catch (bytes memory reason) { + // Verify it's not a router error (which would be "ROUTER_INVALID_SIGNATURE") + // Any other error means the router successfully routed to the pools service + string memory revertReason = string(reason); + assertFalse( + keccak256(abi.encodePacked(revertReason)) == keccak256(abi.encodePacked("ROUTER_INVALID_SIGNATURE")), + "Router should route to pools service, not return INVALID_SIGNATURE" + ); + } + } +} diff --git a/test/arbitrum/wstETH/ArbitrumForkAmmWstEthSwapsUnwind.t.sol b/test/arbitrum/wstETH/ArbitrumForkAmmWstEthSwapsUnwind.t.sol index 8c18f21a7..fb5dfb16f 100644 --- a/test/arbitrum/wstETH/ArbitrumForkAmmWstEthSwapsUnwind.t.sol +++ b/test/arbitrum/wstETH/ArbitrumForkAmmWstEthSwapsUnwind.t.sol @@ -569,6 +569,7 @@ contract ArbitrumForkAmmWstEthSwapsUnwindTest is ArbitrumTestForkCommons { _init(); _createAmmCloseSwapServiceStEthUnwindCase1(); _updateIporRouterImplementation(); + _setupAssetServices(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); @@ -594,7 +595,7 @@ contract ArbitrumForkAmmWstEthSwapsUnwindTest is ArbitrumTestForkCommons { 1, messageSignerPrivateKey ); - + IIporOracle(iporOracleProxy).addUpdater(owner); vm.prank(owner); @@ -638,6 +639,7 @@ contract ArbitrumForkAmmWstEthSwapsUnwindTest is ArbitrumTestForkCommons { _init(); _createAmmCloseSwapServiceStEthUnwindCase1(); _updateIporRouterImplementation(); + _setupAssetServices(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); @@ -699,6 +701,7 @@ contract ArbitrumForkAmmWstEthSwapsUnwindTest is ArbitrumTestForkCommons { _init(); _createAmmCloseSwapServiceStEthUnwindCase1(); _updateIporRouterImplementation(); + _setupAssetServices(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); @@ -760,6 +763,7 @@ contract ArbitrumForkAmmWstEthSwapsUnwindTest is ArbitrumTestForkCommons { _init(); _createAmmCloseSwapServiceStEthUnwindCase1(); _updateIporRouterImplementation(); + _setupAssetServices(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); diff --git a/test/base/SwapLogicBaseV1/IporSwapLogicCalculateSwapAmount.t.sol b/test/base/SwapLogicBaseV1/IporSwapLogicCalculateSwapAmount.t.sol index 5212e8a74..17f9f97c9 100644 --- a/test/base/SwapLogicBaseV1/IporSwapLogicCalculateSwapAmount.t.sol +++ b/test/base/SwapLogicBaseV1/IporSwapLogicCalculateSwapAmount.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../../utils/DataUtils.sol"; -import "../../TestCommons.sol"; +import "../../../test/TestCommons.sol"; import "../../mocks/MockSwapLogicBaseV1.sol"; contract IporSwapLogicCalculateInterest is TestCommons, DataUtils { diff --git a/test/base/SwapLogicBaseV1/SwapLogicCalculateInterest.t.sol b/test/base/SwapLogicBaseV1/SwapLogicCalculateInterest.t.sol index 84fbd409c..65dbe3abb 100644 --- a/test/base/SwapLogicBaseV1/SwapLogicCalculateInterest.t.sol +++ b/test/base/SwapLogicBaseV1/SwapLogicCalculateInterest.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../../utils/DataUtils.sol"; -import "../../TestCommons.sol"; +import "../../../test/TestCommons.sol"; import "../../utils/TestConstants.sol"; import "../../mocks/MockSwapLogicBaseV1.sol"; import "../../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/base/SwapLogicBaseV1/SwapLogicCalculateSwapPayFixedValue.t.sol b/test/base/SwapLogicBaseV1/SwapLogicCalculateSwapPayFixedValue.t.sol index 4864df26e..1e8a49ea9 100644 --- a/test/base/SwapLogicBaseV1/SwapLogicCalculateSwapPayFixedValue.t.sol +++ b/test/base/SwapLogicBaseV1/SwapLogicCalculateSwapPayFixedValue.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../../utils/DataUtils.sol"; -import "../../TestCommons.sol"; +import "../../../test/TestCommons.sol"; import "../../utils/TestConstants.sol"; import "../../mocks/MockSwapLogicBaseV1.sol"; import "../../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/base/SwapLogicBaseV1/SwapLogicCalculateSwapReceiveFixedValue.t.sol b/test/base/SwapLogicBaseV1/SwapLogicCalculateSwapReceiveFixedValue.t.sol index 92fb9bb54..441df2b6a 100644 --- a/test/base/SwapLogicBaseV1/SwapLogicCalculateSwapReceiveFixedValue.t.sol +++ b/test/base/SwapLogicBaseV1/SwapLogicCalculateSwapReceiveFixedValue.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import {DataUtils} from "../../utils/DataUtils.sol"; -import "../../TestCommons.sol"; +import "../../../test/TestCommons.sol"; import "../../utils/TestConstants.sol"; import "../../mocks/MockSwapLogicBaseV1.sol"; import "../../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/chain-base/BaseForkAmmWstEthCloseSwaps.t.sol b/test/chain-base/BaseForkAmmWstEthCloseSwaps.t.sol index ca1c9ca52..77e9a4dbf 100644 --- a/test/chain-base/BaseForkAmmWstEthCloseSwaps.t.sol +++ b/test/chain-base/BaseForkAmmWstEthCloseSwaps.t.sol @@ -6,6 +6,8 @@ import "./BaseTestForkCommons.sol"; import {IAmmCloseSwapServiceWstEth} from "../../contracts/interfaces/IAmmCloseSwapServiceWstEth.sol"; import {AmmTypes} from "../../contracts/interfaces/types/AmmTypes.sol"; import {AmmStorageBaseV1} from "../../contracts/base/amm/AmmStorageBaseV1.sol"; +import {AmmOpenSwapServiceWstEthBaseV1} from "../../contracts/base/amm-wstEth/services/AmmOpenSwapServiceWstEthBaseV1.sol"; +import {IAmmOpenSwapServiceWstEth} from "../../contracts/interfaces/IAmmOpenSwapServiceWstEth.sol"; import {IAmmPoolsServiceWstEthBaseV2} from "../../contracts/base/amm-wstEth/interfaces/IAmmPoolsServiceWstEthBaseV2.sol"; contract BaseForkAmmWstEthCloseSwapsTest is BaseTestForkCommons { diff --git a/test/chain-base/BaseTestForkCommons.sol b/test/chain-base/BaseTestForkCommons.sol index 2e357348b..e7430f74f 100644 --- a/test/chain-base/BaseTestForkCommons.sol +++ b/test/chain-base/BaseTestForkCommons.sol @@ -4,23 +4,14 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import {IWETH9} from "../../contracts/amm-eth/interfaces/IWETH9.sol"; - import "../../contracts/interfaces/IAmmCloseSwapLens.sol"; import "../../contracts/chains/ethereum/amm-commons/AmmSwapsLens.sol"; -import "../../contracts/chains/arbitrum/amm-wstEth/AmmOpenSwapServiceWstEth.sol"; -import "../../contracts/chains/arbitrum/amm-wstEth/AmmCloseSwapServiceWstEth.sol"; import "../../contracts/amm/AmmPoolsService.sol"; -import "../../contracts/chains/arbitrum/amm-commons/AmmCloseSwapLensArbitrum.sol"; import "../../contracts/chains/arbitrum/amm-commons/AmmGovernanceServiceArbitrum.sol"; import {StorageLibArbitrum} from "../../contracts/chains/arbitrum/libraries/StorageLibArbitrum.sol"; - import {AmmTreasuryBaseV2} from "../../contracts/base/amm/AmmTreasuryBaseV2.sol"; - - import {AmmPoolsServiceWstEthBaseV2} from "../../contracts/base/amm-wstEth/services/AmmPoolsServiceWstEthBaseV2.sol"; - import {AmmCloseSwapServiceWstEthBaseV2} from "../../contracts/base/amm-wstEth/services/AmmCloseSwapServiceWstEthBaseV2.sol"; - import {IporProtocolRouterBase} from "../../contracts/chains/base/router/IporProtocolRouterBase.sol"; @@ -73,7 +64,7 @@ contract BaseTestForkCommons is Test { ammOpenSwapServiceWstEth = 0xFbE094Bcc8731fa45Eb88850592248e5D6aC9472; - // _createAmmOpenSwapServiceWstEth(); + // _createAmmOpenSwapServiceWstEth(); _createAmmCloseSwapServiceWstEth(); _setupAssetServices(); @@ -200,29 +191,6 @@ contract BaseTestForkCommons is Test { } - - - // function _createAmmOpenSwapServiceWstEth() private { - // ammOpenSwapServiceWstEth = address( - // new AmmOpenSwapServiceWstEth({ - // poolCfg: AmmTypesBaseV1.AmmOpenSwapServicePoolConfiguration({ - // asset: wstETH, - // decimals: IERC20MetadataUpgradeable(wstETH).decimals(), - // ammStorage: ammStorageWstEthProxy, - // ammTreasury: ammTreasuryWstEthProxy, - // spread: spreadWstEth, - // iporPublicationFee: 10 * 1e15, - // maxSwapCollateralAmount: 100_000 * 1e18, - // liquidationDepositAmount: 1000, - // minLeverage: 10 * 1e18, - // openingFeeRate: 5e14, - // openingFeeTreasuryPortionRate: 5e17 - // }), - // iporOracle_: iporOracleProxy - // }) - // ); - // } - function _createAmmCloseSwapServiceWstEth() private { ammCloseSwapServiceWstEth = address( new AmmCloseSwapServiceWstEthBaseV2({ diff --git a/test/fork/ForkAmmStEthExchangeRate.t.sol b/test/fork/ForkAmmStEthExchangeRate.t.sol index c5fad2a5e..937ca4ec6 100644 --- a/test/fork/ForkAmmStEthExchangeRate.t.sol +++ b/test/fork/ForkAmmStEthExchangeRate.t.sol @@ -19,14 +19,14 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { uint256 provideAmount = 1 ether; - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); // when vm.prank(user); IAmmPoolsServiceStEth(iporProtocolRouterProxy).provideLiquidityStEth(user, provideAmount); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -39,14 +39,14 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { uint256 provideAmount = 1 ether; - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); // when vm.prank(user); IAmmPoolsServiceStEth(iporProtocolRouterProxy).provideLiquidityWEth(user, provideAmount); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -59,14 +59,14 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { uint256 provideAmount = 1 ether; - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); // when vm.prank(user); IAmmPoolsServiceStEth(iporProtocolRouterProxy).provideLiquidityEth{value: provideAmount}(user, provideAmount); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -79,7 +79,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { uint256 provideAmount = 1 ether; - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); // when vm.startPrank(user); @@ -89,7 +89,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { vm.stopPrank(); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertLt(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -102,7 +102,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { uint256 provideAmount = 1 ether; - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); // when vm.startPrank(user); @@ -112,7 +112,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { vm.stopPrank(); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertLt(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -125,7 +125,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { uint256 provideAmount = 1 ether; - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); // when vm.startPrank(user); @@ -135,7 +135,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { vm.stopPrank(); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertLt(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -144,14 +144,13 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { // given _init(); _createNewAmmPoolsServiceStEthWithZEROFee(); - _updateIporRouterImplementation(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); uint256 provideAmount = 1 ether; - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); // when vm.startPrank(user); @@ -161,7 +160,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { vm.stopPrank(); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -193,7 +192,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -207,7 +206,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -239,7 +238,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -253,7 +252,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -285,7 +284,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -294,7 +293,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { }(user, ETH, totalAmount, 1e18, 10e18, riskIndicatorsInputs); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -326,7 +325,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -340,7 +339,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -372,7 +371,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -386,7 +385,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -418,7 +417,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -432,7 +431,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -464,7 +463,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -473,7 +472,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { }(user, ETH, totalAmount, 1e18, 10e18, riskIndicatorsInputs); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -505,7 +504,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -519,7 +518,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -551,7 +550,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -565,7 +564,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -597,7 +596,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -611,7 +610,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -643,7 +642,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -652,7 +651,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { }(user, ETH, totalAmount, 1e18, 10e18, riskIndicatorsInputs); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -684,7 +683,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -698,7 +697,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -730,7 +729,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -744,7 +743,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -776,7 +775,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -790,7 +789,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -822,7 +821,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -831,7 +830,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { }(user, ETH, totalAmount, 0, 10e18, riskIndicatorsInputs); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -863,7 +862,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -877,7 +876,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -909,7 +908,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -923,7 +922,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -955,7 +954,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -969,7 +968,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1001,7 +1000,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1010,7 +1009,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { }(user, ETH, totalAmount, 0, 10e18, riskIndicatorsInputs); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1042,7 +1041,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1056,7 +1055,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1088,7 +1087,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1102,7 +1101,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1134,7 +1133,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1148,7 +1147,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1180,7 +1179,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1189,7 +1188,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { }(user, ETH, totalAmount, 0, 10e18, riskIndicatorsInputs); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1221,7 +1220,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1235,7 +1234,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertNotEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1248,7 +1247,6 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { /// @dev setup opening fee to zero _createAmmOpenSwapServiceStEthCase2(); - _updateIporRouterImplementation(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); @@ -1274,7 +1272,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1288,7 +1286,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1301,7 +1299,6 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { /// @dev setup opening fee to zero _createAmmOpenSwapServiceStEthCase2(); - _updateIporRouterImplementation(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); @@ -1327,7 +1324,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1341,7 +1338,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1352,7 +1349,6 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { /// @dev setup opening fee to zero _createAmmOpenSwapServiceStEthCase2(); - _updateIporRouterImplementation(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); @@ -1378,7 +1374,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1387,7 +1383,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { }(user, ETH, totalAmount, 1e18, 10e18, riskIndicatorsInputs); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1400,7 +1396,6 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { /// @dev setup opening fee to zero _createAmmOpenSwapServiceStEthCase2(); - _updateIporRouterImplementation(); address user = _getUserAddress(22); _setupUser(user, 1000 * 1e18); @@ -1426,7 +1421,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1440,7 +1435,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1500,7 +1495,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { closeRiskIndicatorsInputs ); AmmTypesBaseV1.Balance memory balance = AmmStorageBaseV1(ammStorageProxyStEth).getBalance(); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint256 balancePublicationFeeBefore = AmmStorageBaseV1(ammStorageProxyStEth).getBalance().iporPublicationFee; @@ -1509,7 +1504,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { IAmmGovernanceService(iporProtocolRouterProxy).transferToCharlieTreasury(stETH, balancePublicationFeeBefore); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint256 balancePublicationFeeAfter = AmmStorageBaseV1(ammStorageProxyStEth).getBalance().iporPublicationFee; assertEq(balancePublicationFeeAfter, 0, "iporPublicationFee after"); @@ -1572,7 +1567,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { closeRiskIndicatorsInputs ); AmmTypesBaseV1.Balance memory balance = AmmStorageBaseV1(ammStorageProxyStEth).getBalance(); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint256 balanceTreasuryBefore = AmmStorageBaseV1(ammStorageProxyStEth).getBalance().treasury; @@ -1581,7 +1576,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { IAmmGovernanceService(iporProtocolRouterProxy).transferToTreasury(stETH, balanceTreasuryBefore); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint256 balanceTreasuryAfter = AmmStorageBaseV1(ammStorageProxyStEth).getBalance().treasury; assertEq(balanceTreasuryAfter, 0, "iporPublicationFee after"); @@ -1600,7 +1595,6 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { /// @dev setup opening fee to zero _createAmmOpenSwapServiceStEthCase3(); - _updateIporRouterImplementation(); AmmTypes.RiskIndicatorsInputs memory riskIndicatorsInputs = AmmTypes.RiskIndicatorsInputs({ maxCollateralRatio: 50000000000000000, @@ -1621,7 +1615,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1636,7 +1630,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1651,7 +1645,6 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { /// @dev setup opening fee to zero _createAmmOpenSwapServiceStEthCase3(); - _updateIporRouterImplementation(); AmmTypes.RiskIndicatorsInputs memory riskIndicatorsInputs = AmmTypes.RiskIndicatorsInputs({ maxCollateralRatio: 50000000000000000, @@ -1672,7 +1665,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1687,7 +1680,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1702,7 +1695,6 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { /// @dev setup opening fee to zero _createAmmOpenSwapServiceStEthCase3(); - _updateIporRouterImplementation(); AmmTypes.RiskIndicatorsInputs memory riskIndicatorsInputs = AmmTypes.RiskIndicatorsInputs({ maxCollateralRatio: 50000000000000000, @@ -1723,7 +1715,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1737,7 +1729,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { ); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } @@ -1752,7 +1744,6 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { /// @dev setup opening fee to zero _createAmmOpenSwapServiceStEthCase3(); - _updateIporRouterImplementation(); AmmTypes.RiskIndicatorsInputs memory riskIndicatorsInputs = AmmTypes.RiskIndicatorsInputs({ maxCollateralRatio: 50000000000000000, @@ -1773,7 +1764,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { messageSignerPrivateKey ); - uint256 exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); //when vm.prank(user); @@ -1782,7 +1773,7 @@ contract ForkAmmStEthExchangeRateTest is TestForkCommons { }(user, ETH, totalAmount, 1e18, 10e18, riskIndicatorsInputs); //then - uint256 exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint256 exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(exchangeRateBefore, exchangeRateAfter, "Exchange rate should not change"); } } diff --git a/test/fork/ForkAmmStEthOpenSwaps.t.sol b/test/fork/ForkAmmStEthOpenSwaps.t.sol index cf335cfc3..c25754832 100644 --- a/test/fork/ForkAmmStEthOpenSwaps.t.sol +++ b/test/fork/ForkAmmStEthOpenSwaps.t.sol @@ -2057,6 +2057,7 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { //given _init(); address user = _getUserAddress(22); + deal(user, 123); uint256 totalAmount = 1e17; @@ -2629,6 +2630,7 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { //given _init(); address user = _getUserAddress(22); + deal(user, 123); uint256 totalAmount = 1e17; @@ -3152,7 +3154,7 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { uint userOneStEthBalanceBefore = IStETH(stETH).balanceOf(user); uint userOneIpstEthBalanceBefore = IERC20(ipstETH).balanceOf(user); uint ammTreasuryStEthBalanceBefore = IStETH(stETH).balanceOf(ammTreasuryProxyStEth); - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint provideAmount = 1 * 1e18; @@ -3164,7 +3166,7 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { uint userOneStEthBalanceAfter = IStETH(stETH).balanceOf(user); uint userOneIpstEthBalanceAfter = IERC20(ipstETH).balanceOf(user); uint ammTreasuryStEthBalanceAfter = IStETH(stETH).balanceOf(ammTreasuryProxyStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq( userOneStEthBalanceBefore - provideAmount, @@ -3231,7 +3233,7 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { uint userWEthBalanceBefore = IWETH9(wETH).balanceOf(user); uint userOneIpstEthBalanceBefore = IERC20(ipstETH).balanceOf(user); uint ammTreasuryStEthBalanceBefore = IStETH(stETH).balanceOf(ammTreasuryProxyStEth); - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint provideAmount = 1 * 1e18; @@ -3243,7 +3245,7 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { uint userWEthBalanceAfter = IWETH9(wETH).balanceOf(user); uint userOneIpstEthBalanceAfter = IERC20(ipstETH).balanceOf(user); uint ammTreasuryStEthBalanceAfter = IStETH(stETH).balanceOf(ammTreasuryProxyStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(userWEthBalanceBefore - provideAmount, userWEthBalanceAfter, "user balance of wEth should decrease"); assertLt(userOneIpstEthBalanceBefore, userOneIpstEthBalanceAfter, "user balance of ipstEth should increase"); @@ -3306,7 +3308,7 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { uint userEthBalanceBefore = user.balance; uint userOneIpstEthBalanceBefore = IERC20(ipstETH).balanceOf(user); uint ammTreasuryStEthBalanceBefore = IStETH(stETH).balanceOf(ammTreasuryProxyStEth); - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint exchangeRateBefore = IAmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint provideAmount = 1 * 1e18; @@ -3318,7 +3320,7 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { uint userEthBalanceAfter = user.balance; uint userOneIpstEthBalanceAfter = IERC20(ipstETH).balanceOf(user); uint ammTreasuryStEthBalanceAfter = IStETH(stETH).balanceOf(ammTreasuryProxyStEth); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint exchangeRateAfter = IAmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); assertEq(userEthBalanceBefore - provideAmount, userEthBalanceAfter, "user balance of Eth should decrease"); assertLt(userOneIpstEthBalanceBefore, userOneIpstEthBalanceAfter, "user balance of ipstEth should increase"); @@ -3331,5 +3333,4 @@ contract ForkAmmStEthOpenSwapsTest is TestForkCommons { assertEq(exchangeRateBefore, exchangeRateAfter, "exchangeRate should not change"); } - } diff --git a/test/fork/ForkIporProtocolRouterCases.t.sol b/test/fork/ForkIporProtocolRouterCases.t.sol index 07f7d698a..af650caf9 100644 --- a/test/fork/ForkIporProtocolRouterCases.t.sol +++ b/test/fork/ForkIporProtocolRouterCases.t.sol @@ -6,6 +6,8 @@ import "./TestForkCommons.sol"; import "../../contracts/interfaces/IAmmCloseSwapServiceStEth.sol"; import "../../contracts/interfaces/types/AmmTypes.sol"; import "../contracts/IporClient.sol"; +import {IporProtocolRouterEthereum} from "../../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; +import {AmmPoolsLensBaseV1} from "../../contracts/base/amm/services/AmmPoolsLensBaseV1.sol"; contract ForkIporProtocolRouterCases is TestForkCommons { function setUp() public { @@ -348,7 +350,7 @@ contract ForkIporProtocolRouterCases is TestForkCommons { uint userStEthBalanceBefore = IStETH(stETH).balanceOf(user); uint userWEthBalanceBefore = IERC20(wETH).balanceOf(user); - uint exchangeRateBefore = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint exchangeRateBefore = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint ammTreasuryStEthBalanceBefore = IStETH(stETH).balanceOf(ammTreasuryProxyStEth); bytes[] memory requestData = new bytes[](3); @@ -374,14 +376,14 @@ contract ForkIporProtocolRouterCases is TestForkCommons { // when vm.prank(user); - IporProtocolRouter(iporProtocolRouterProxy).batchExecutor{value: 150e18}(requestData); + IporProtocolRouterEthereum(iporProtocolRouterProxy).batchExecutor{value: 150e18}(requestData); // then uint userIpstEthBalanceAfter = IERC20(ipstETH).balanceOf(user); uint userStEthBalanceAfter = IStETH(stETH).balanceOf(user); uint userWethBalanceAfter = IERC20(wETH).balanceOf(user); - uint exchangeRateAfter = IAmmPoolsLensStEth(iporProtocolRouterProxy).getIpstEthExchangeRate(); + uint exchangeRateAfter = AmmPoolsLensBaseV1(iporProtocolRouterProxy).getIpTokenExchangeRate(stETH); uint ammTreasuryStEthBalanceAfter = IStETH(stETH).balanceOf(ammTreasuryProxyStEth); assertEq(user.balance, userEthBalanceBefore - 100e18 + 12345, " user balance with additional eth 12345"); diff --git a/test/fork/TestForkCommons.sol b/test/fork/TestForkCommons.sol index 4766a3eac..3da3b719d 100644 --- a/test/fork/TestForkCommons.sol +++ b/test/fork/TestForkCommons.sol @@ -6,13 +6,12 @@ import "forge-std/console2.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "../../contracts/oracles/IporOracle.sol"; import "../mocks/EmptyRouterImplementation.sol"; -import "../../contracts/chains/ethereum/router/IporProtocolRouter.sol"; +import "../../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; import "../../contracts/interfaces/IAmmSwapsLens.sol"; import "../../contracts/interfaces/IAmmOpenSwapLens.sol"; import "../../contracts/interfaces/IAmmCloseSwapLens.sol"; -import "../../contracts/chains/ethereum/amm-commons/AmmSwapsLens.sol"; -import "../../contracts/amm/AmmPoolsLens.sol"; -import "../../contracts/amm-eth/AmmPoolsLensStEth.sol"; +import "../../contracts/base/amm/services/AmmSwapsLensBaseV1.sol"; +import "../../contracts/base/amm/services/AmmPoolsLensBaseV1.sol"; import "../../contracts/amm/AssetManagementLens.sol"; import "../../contracts/amm/spread/Spread28Days.sol"; import "../../contracts/amm/spread/Spread60Days.sol"; @@ -21,27 +20,30 @@ import "../../contracts/amm/spread/SpreadCloseSwapService.sol"; import "../../contracts/amm/spread/SpreadStorageLens.sol"; import "../../contracts/amm/spread/SpreadRouter.sol"; import "../../contracts/amm/AmmOpenSwapService.sol"; -import "../../contracts/amm-eth/AmmOpenSwapServiceStEth.sol"; +import "../../contracts/chains/ethereum/amm-stEth/AmmOpenSwapServiceStEth.sol"; import "../../contracts/amm/AmmCloseSwapServiceUsdt.sol"; import "../../contracts/amm/AmmCloseSwapServiceUsdc.sol"; import "../../contracts/amm/AmmCloseSwapServiceDai.sol"; -import "../../contracts/amm-eth/AmmCloseSwapServiceStEth.sol"; -import "../../contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol"; +import {AmmCloseSwapServiceStEthBaseV2} from "../../contracts/base/amm-stEth/services/AmmCloseSwapServiceStEthBaseV2.sol"; +import "../../contracts/base/amm/services/AmmCloseSwapLensBaseV1.sol"; import "../../contracts/amm/AmmPoolsService.sol"; -import "../../contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol"; +import "../../contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol"; +import "../../contracts/base/libraries/StorageLibBaseV1.sol"; import "../../contracts/amm/AmmStorage.sol"; import "../../contracts/amm/AmmTreasury.sol"; -import "../../contracts/amm-eth/AmmPoolsServiceStEth.sol"; import "../../contracts/interfaces/IIpTokenV1.sol"; import "../../contracts/amm-eth/interfaces/IWETH9.sol"; import "../../contracts/amm-eth/interfaces/IStETH.sol"; import "../../contracts/base/amm/AmmStorageBaseV1.sol"; import "../../contracts/base/amm/AmmTreasuryBaseV1.sol"; +import "../../contracts/base/amm/AmmTreasuryBaseV2.sol"; import "../../contracts/base/spread/SpreadBaseV1.sol"; import "../../contracts/amm/spread/SpreadStorageService.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {MockPlasmaVault} from "../mocks/tokens/MockPlasmaVault.sol"; +import {AmmSwapsLens} from "../../contracts/chains/ethereum/amm-commons/AmmSwapsLens.sol"; +import {AmmPoolsServiceStEth} from "../../contracts/chains/ethereum/amm-stEth/AmmPoolsServiceStEth.sol"; contract TestForkCommons is Test { address public constant owner = 0xD92E9F039E4189c342b4067CC61f5d063960D248; @@ -68,6 +70,8 @@ contract TestForkCommons is Test { address public constant ipUSDC = 0x7c0e72f431FD69560D951e4C04A4de3657621a88; address public constant ipUSDT = 0x9Bd2177027edEE300DC9F1fb88F24DB6e5e1edC6; address public constant ipstETH = 0xc40431b6C510AeB45Fbb5e21E40D49F12b0c1F0c; + address public constant ipWeEth = 0xaC5B04988BC71bEE96f8D93040777Db3ef166125; + address public constant ipUsdm = 0x9aC5092E027F0d9F24B4a1065C70973f3AFda4cB; address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address public constant stETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84; @@ -97,13 +101,16 @@ contract TestForkCommons is Test { address public ammTreasuryProxyStEth = 0x63395EDAF74a80aa1155dB7Cd9BBA976a88DeE4E; + address public ammTreasuryProxyWeEth = 0xcC2fF2D38666723ea56c122097F6215B90d74196; + address public ammStorageProxyWeEth = 0x77Fe3a8E8d1d73Df54Ca07674Bf1bD6C5841e3b5; + uint256 public messageSignerPrivateKey; address public messageSignerAddress; address public ammStorageProxyStEth; address public ammOpenSwapServiceStEth; address public ammCloseSwapServiceStEth; - address public ammPoolsLensStEth; + address public ammPoolsServiceStEth; address public ammStorageProxyUsdm; @@ -127,9 +134,11 @@ contract TestForkCommons is Test { address public newPlasmaVaultUsdt; address public newPlasmaVaultUsdc; address public newPlasmaVaultDai; + address public newPlasmaVaultStEth; address public newAmmPoolsService; address public newAmmPoolsLens; + address public newAmmPoolsLensBaseV1; address public newAmmAssetManagementLens; address public newAmmSwapsLens; address public newAmmOpenSwapService; @@ -161,7 +170,6 @@ contract TestForkCommons is Test { _createAmmOpenSwapServiceStEth(); _createAmmCloseSwapServiceStEth(); _createNewAmmPoolsServiceStEth(); - _createAmmPoolsLensStEth(); _createAmmCloseSwapLens(); @@ -170,6 +178,10 @@ contract TestForkCommons is Test { _setupIporOracleStEth(); _updateIporRouterImplementation(); + + _setupAmmGovernanceService(); + _setupAssetLensData(); + _setupAssetServices(); } function _setupUser(address user, uint256 value) internal { @@ -231,35 +243,8 @@ contract TestForkCommons is Test { } function _createAmmPoolsLens() internal { - newAmmPoolsLens = address( - new AmmPoolsLens({ - usdtPoolCfg: IAmmPoolsLens.AmmPoolsLensPoolConfiguration({ - asset: USDT, - decimals: 6, - ipToken: ipUSDT, - ammStorage: ammStorageProxyUsdt, - ammTreasury: ammTreasuryUsdt, - assetManagement: newPlasmaVaultUsdt - }), - usdcPoolCfg: IAmmPoolsLens.AmmPoolsLensPoolConfiguration({ - asset: USDC, - decimals: 6, - ipToken: ipUSDC, - ammStorage: ammStorageProxyUsdc, - ammTreasury: ammTreasuryUsdc, - assetManagement: newPlasmaVaultUsdc - }), - daiPoolCfg: IAmmPoolsLens.AmmPoolsLensPoolConfiguration({ - asset: DAI, - decimals: 18, - ipToken: ipDAI, - ammStorage: ammStorageProxyDai, - ammTreasury: ammTreasuryDai, - assetManagement: newPlasmaVaultDai - }), - iporOracleInput: iporOracleProxy - }) - ); + ///TODO: check if newAmmPoolsLens old one are needed here + newAmmPoolsLensBaseV1 = address(new AmmPoolsLensBaseV1({iporOracle_: iporOracleProxy})); } function _createAmmAssetManagementLens() internal { @@ -288,17 +273,16 @@ contract TestForkCommons is Test { } function _updateIporRouterImplementation() internal { - IporProtocolRouter newImplementation = new IporProtocolRouter( - IporProtocolRouter.DeployedContracts( + IporProtocolRouterEthereum newImplementation = new IporProtocolRouterEthereum( + IporProtocolRouterEthereum.DeployedContracts( newAmmSwapsLens, - newAmmPoolsLens, + newAmmPoolsLensBaseV1, + newAmmPoolsLensBaseV1, // ammPoolsLensBaseV1 - reuse same lens newAmmAssetManagementLens, newAmmOpenSwapService, - ammOpenSwapServiceStEth, newAmmCloseSwapServiceUsdt, newAmmCloseSwapServiceUsdc, newAmmCloseSwapServiceDai, - ammCloseSwapServiceStEth, newAmmCloseSwapLens, newAmmPoolsService, newAmmGovernanceService, @@ -306,16 +290,13 @@ contract TestForkCommons is Test { _getUserAddress(123), _getUserAddress(123), _getUserAddress(123), - ammPoolsServiceStEth, - ammPoolsLensStEth, - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123), - _getUserAddress(123) + stETH, + weETH, + USDM ) ); vm.prank(owner); - IporProtocolRouter(iporProtocolRouterProxy).upgradeTo(address(newImplementation)); + IporProtocolRouterEthereum(iporProtocolRouterProxy).upgradeTo(address(newImplementation)); } function _getUserAddress(uint256 number) internal returns (address) { @@ -349,6 +330,7 @@ contract TestForkCommons is Test { newPlasmaVaultUsdt = address(new MockPlasmaVault(IERC20(USDT), "ipUSDTfusion", "ipUSDTfusion")); newPlasmaVaultUsdc = address(new MockPlasmaVault(IERC20(USDC), "ipUSDCfusion", "ipUSDCfusion")); newPlasmaVaultDai = address(new MockPlasmaVault(IERC20(DAI), "ipDAIfusion", "ipDAIfusion")); + newPlasmaVaultStEth = address(new MockPlasmaVault(IERC20(stETH), "ipstETHfusion", "ipstETHfusion")); } function _createAmmSwapsLens() private { @@ -383,46 +365,64 @@ contract TestForkCommons is Test { ); } - function _createAmmPoolsLensStEth() private { - ammPoolsLensStEth = address( - new AmmPoolsLensStEth(stETH, ipstETH, ammTreasuryProxyStEth, ammStorageProxyStEth, iporOracleProxy) - ); - } - function _createNewAmmPoolsServiceStEth() private { ammPoolsServiceStEth = address( - new AmmPoolsServiceStEth( - stETH, - wETH, - ipstETH, - ammTreasuryProxyStEth, - ammStorageProxyStEth, - iporOracleProxy, - iporProtocolRouterProxy, - 5000000000000000 - ) + new AmmPoolsServiceStEth({ + stEth_: stETH, + wEth_: wETH, + ipToken_: ipstETH, + ammTreasury_: ammTreasuryProxyStEth, + ammStorage_: ammStorageProxyStEth, + ammAssetManagement_: newPlasmaVaultStEth, + iporOracle_: iporOracleProxy, + iporProtocolRouter_: iporProtocolRouterProxy, + redeemFeeRate_: 5000000000000000, + autoRebalanceThresholdMultiplier_: 1 + }) ); } function _createNewAmmPoolsServiceStEthWithZEROFee() internal { ammPoolsServiceStEth = address( - new AmmPoolsServiceStEth( - stETH, - wETH, - ipstETH, - ammTreasuryProxyStEth, - ammStorageProxyStEth, - iporOracleProxy, - iporProtocolRouterProxy, - 0 - ) + new AmmPoolsServiceStEth({ + stEth_: stETH, + wEth_: wETH, + ipToken_: ipstETH, + ammTreasury_: ammTreasuryProxyStEth, + ammStorage_: ammStorageProxyStEth, + ammAssetManagement_: newPlasmaVaultStEth, + iporOracle_: iporOracleProxy, + iporProtocolRouter_: iporProtocolRouterProxy, + redeemFeeRate_: 0, + autoRebalanceThresholdMultiplier_: 1 + }) + ); + + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + stETH, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: ammPoolsServiceStEth, + ammOpenSwapService: ammOpenSwapServiceStEth, + ammCloseSwapService: ammCloseSwapServiceStEth + }) ); } function _createNewAmmGovernanceService() private { - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory usdtPoolCfg = IAmmGovernanceLens - .AmmGovernancePoolConfiguration({ - asset: USDT, + newAmmGovernanceService = address(new AmmGovernanceServiceBaseV1()); + } + + function _setupAmmGovernanceService() private { + vm.startPrank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setMessageSigner(messageSignerAddress); + vm.stopPrank(); + + // Setup USDT pool + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + USDT, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ decimals: 6, ammStorage: ammStorageProxyUsdt, ammTreasury: ammTreasuryUsdt, @@ -431,10 +431,14 @@ contract TestForkCommons is Test { ammPoolsTreasuryManager: treasurer, ammCharlieTreasury: treasurer, ammCharlieTreasuryManager: treasurer - }); - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory usdcPoolCfg = IAmmGovernanceLens - .AmmGovernancePoolConfiguration({ - asset: USDC, + }) + ); + + // Setup USDC pool + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + USDC, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ decimals: 6, ammStorage: ammStorageProxyUsdc, ammTreasury: ammTreasuryUsdc, @@ -443,10 +447,14 @@ contract TestForkCommons is Test { ammPoolsTreasuryManager: treasurer, ammCharlieTreasury: treasurer, ammCharlieTreasuryManager: treasurer - }); - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory daiPoolCfg = IAmmGovernanceLens - .AmmGovernancePoolConfiguration({ - asset: DAI, + }) + ); + + // Setup DAI pool + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + DAI, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ decimals: 18, ammStorage: ammStorageProxyDai, ammTreasury: ammTreasuryDai, @@ -455,11 +463,14 @@ contract TestForkCommons is Test { ammPoolsTreasuryManager: treasurer, ammCharlieTreasury: treasurer, ammCharlieTreasuryManager: treasurer - }); + }) + ); - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory stEthPoolCfg = IAmmGovernanceLens - .AmmGovernancePoolConfiguration({ - asset: stETH, + // Setup stETH pool + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + stETH, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ decimals: 18, ammStorage: ammStorageProxyStEth, ammTreasury: ammTreasuryProxyStEth, @@ -468,11 +479,14 @@ contract TestForkCommons is Test { ammPoolsTreasuryManager: treasurer, ammCharlieTreasury: treasurer, ammCharlieTreasuryManager: treasurer - }); + }) + ); - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory weETHPoolCfg = IAmmGovernanceLens - .AmmGovernancePoolConfiguration({ - asset: weETH, + // Setup weETH pool + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + weETH, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ decimals: 18, ammStorage: ammStorageProxyStEth, ammTreasury: ammTreasuryProxyStEth, @@ -481,11 +495,14 @@ contract TestForkCommons is Test { ammPoolsTreasuryManager: treasurer, ammCharlieTreasury: treasurer, ammCharlieTreasuryManager: treasurer - }); + }) + ); - IAmmGovernanceLens.AmmGovernancePoolConfiguration memory usdmPoolCfg = IAmmGovernanceLens - .AmmGovernancePoolConfiguration({ - asset: USDM, + // Setup USDM pool + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAmmGovernancePoolConfiguration( + USDM, + StorageLibBaseV1.AssetGovernancePoolConfigValue({ decimals: 18, ammStorage: ammStorageProxyUsdm, ammTreasury: ammTreasuryProxyUsdm, @@ -494,18 +511,170 @@ contract TestForkCommons is Test { ammPoolsTreasuryManager: treasurer, ammCharlieTreasury: treasurer, ammCharlieTreasuryManager: treasurer - }); + }) + ); + } + + function _setupAssetLensData() private { + // Setup AssetLensData for USDT + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetLensData( + USDT, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 6, + ipToken: ipUSDT, + ammStorage: ammStorageProxyUsdt, + ammTreasury: ammTreasuryUsdt, + ammVault: newPlasmaVaultUsdt, + spread: spreadRouter + }) + ); + + // Setup AssetLensData for USDC + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetLensData( + USDC, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 6, + ipToken: ipUSDC, + ammStorage: ammStorageProxyUsdc, + ammTreasury: ammTreasuryUsdc, + ammVault: newPlasmaVaultUsdc, + spread: spreadRouter + }) + ); + + // Setup AssetLensData for DAI + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetLensData( + DAI, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 18, + ipToken: ipDAI, + ammStorage: ammStorageProxyDai, + ammTreasury: ammTreasuryDai, + ammVault: newPlasmaVaultDai, + spread: spreadRouter + }) + ); + + // Setup AssetLensData for stETH + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetLensData( + stETH, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 18, + ipToken: ipstETH, + ammStorage: ammStorageProxyStEth, + ammTreasury: ammTreasuryProxyStEth, + ammVault: newPlasmaVaultStEth, + spread: spreadStEth + }) + ); + + // Setup AssetLensData for weETH + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetLensData( + weETH, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 18, + ipToken: ipWeEth, + ammStorage: ammStorageProxyWeEth, + ammTreasury: ammTreasuryProxyWeEth, + ammVault: address(0), + spread: address(0) + }) + ); + + // Setup AssetLensData for USDM + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetLensData( + USDM, + StorageLibBaseV1.AssetLensDataValue({ + decimals: 18, + ipToken: ipUsdm, + ammStorage: ammStorageProxyUsdm, + ammTreasury: ammTreasuryProxyUsdm, + ammVault: address(0), + spread: address(0) + }) + ); + } + + function _setupAssetServices() private { + // Setup AssetServices for USDT + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + USDT, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: newAmmPoolsService, + ammOpenSwapService: newAmmOpenSwapService, + ammCloseSwapService: newAmmCloseSwapServiceUsdt + }) + ); + + // Setup AssetServices for USDC + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + USDC, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: newAmmPoolsService, + ammOpenSwapService: newAmmOpenSwapService, + ammCloseSwapService: newAmmCloseSwapServiceUsdc + }) + ); + + // Setup AssetServices for DAI + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + DAI, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: newAmmPoolsService, + ammOpenSwapService: newAmmOpenSwapService, + ammCloseSwapService: newAmmCloseSwapServiceDai + }) + ); + + // Setup AssetServices for stETH + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + stETH, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: ammPoolsServiceStEth, + ammOpenSwapService: ammOpenSwapServiceStEth, + ammCloseSwapService: ammCloseSwapServiceStEth + }) + ); - newAmmGovernanceService = address( - new AmmGovernanceService(usdtPoolCfg, usdcPoolCfg, daiPoolCfg, stEthPoolCfg, weETHPoolCfg, usdmPoolCfg) + // Setup AssetServices for weETH + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + weETH, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: address(0), + ammOpenSwapService: address(0), + ammCloseSwapService: address(0) + }) + ); + + // Setup AssetServices for USDM + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + USDM, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: address(0), + ammOpenSwapService: address(0), + ammCloseSwapService: address(0) + }) ); } function _upgradeAmmTreasuryStEth() private { - AmmTreasuryBaseV1 newImplementation = new AmmTreasuryBaseV1( + AmmTreasuryBaseV2 newImplementation = new AmmTreasuryBaseV2( stETH, iporProtocolRouterProxy, - ammStorageProxyStEth + ammStorageProxyStEth, + newPlasmaVaultStEth ); vm.prank(owner); @@ -609,9 +778,7 @@ contract TestForkCommons is Test { openingFeeTreasuryPortionRate: 5e17 }); - ammOpenSwapServiceStEth = address( - new AmmOpenSwapServiceStEth(cfg, iporOracleProxy, messageSignerAddress, wETH, wstETH) - ); + ammOpenSwapServiceStEth = address(new AmmOpenSwapServiceStEth(cfg, iporOracleProxy, wETH, wstETH)); } /// @dev case where liquidationDepositAmount is 0 and openingFeeRate is 0 @@ -631,8 +798,16 @@ contract TestForkCommons is Test { openingFeeTreasuryPortionRate: 5e17 }); - ammOpenSwapServiceStEth = address( - new AmmOpenSwapServiceStEth(cfg, iporOracleProxy, messageSignerAddress, wETH, wstETH) + ammOpenSwapServiceStEth = address(new AmmOpenSwapServiceStEth(cfg, iporOracleProxy, wETH, wstETH)); + + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + stETH, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: ammPoolsServiceStEth, + ammOpenSwapService: ammOpenSwapServiceStEth, + ammCloseSwapService: ammCloseSwapServiceStEth + }) ); } @@ -653,8 +828,16 @@ contract TestForkCommons is Test { openingFeeTreasuryPortionRate: 5e17 }); - ammOpenSwapServiceStEth = address( - new AmmOpenSwapServiceStEth(cfg, iporOracleProxy, messageSignerAddress, wETH, wstETH) + ammOpenSwapServiceStEth = address(new AmmOpenSwapServiceStEth(cfg, iporOracleProxy, wETH, wstETH)); + + vm.prank(owner); + AmmGovernanceServiceBaseV1(iporProtocolRouterProxy).setAssetServices( + stETH, + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: ammPoolsServiceStEth, + ammOpenSwapService: ammOpenSwapServiceStEth, + ammCloseSwapService: ammCloseSwapServiceStEth + }) ); } @@ -797,21 +980,7 @@ contract TestForkCommons is Test { } function _createAmmCloseSwapLens() private { - newAmmCloseSwapLens = address( - new AmmCloseSwapLens({ - usdtInput: USDT, - usdcInput: USDC, - daiInput: DAI, - stETHInput: stETH, - iporOracleInput: iporOracleProxy, - messageSignerInput: messageSignerAddress, - spreadRouterInput: spreadRouter, - closeSwapServiceUsdtInput: newAmmCloseSwapServiceUsdt, - closeSwapServiceUsdcInput: newAmmCloseSwapServiceUsdc, - closeSwapServiceDaiInput: newAmmCloseSwapServiceDai, - closeSwapServiceStEthInput: ammCloseSwapServiceStEth - }) - ); + newAmmCloseSwapLens = address(new AmmCloseSwapLensBaseV1({iporOracle_: iporOracleProxy})); } function _createAmmCloseSwapServiceStEth() private { @@ -821,7 +990,7 @@ contract TestForkCommons is Test { decimals: 18, ammStorage: ammStorageProxyStEth, ammTreasury: ammTreasuryProxyStEth, - assetManagement: address(0), + assetManagement: newPlasmaVaultStEth, spread: spreadStEth, unwindingFeeRate: 5e11, unwindingFeeTreasuryPortionRate: 25e16, @@ -838,9 +1007,7 @@ contract TestForkCommons is Test { timeAfterOpenAllowedToCloseSwapWithUnwindingTenor90days: 3 days }); - ammCloseSwapServiceStEth = address( - new AmmCloseSwapServiceStEth(stEthConfig, iporOracleProxy, messageSignerAddress) - ); + ammCloseSwapServiceStEth = address(new AmmCloseSwapServiceStEthBaseV2(stEthConfig, iporOracleProxy)); } function _createAmmCloseSwapServiceStEthUnwindCase1() internal { @@ -850,7 +1017,7 @@ contract TestForkCommons is Test { decimals: 18, ammStorage: ammStorageProxyStEth, ammTreasury: ammTreasuryProxyStEth, - assetManagement: address(0), + assetManagement: newPlasmaVaultStEth, spread: spreadStEth, unwindingFeeRate: 5e11, unwindingFeeTreasuryPortionRate: 25e16, @@ -867,9 +1034,7 @@ contract TestForkCommons is Test { timeAfterOpenAllowedToCloseSwapWithUnwindingTenor90days: 90 days }); - ammCloseSwapServiceStEth = address( - new AmmCloseSwapServiceStEth(stEthConfig, iporOracleProxy, messageSignerAddress) - ); + ammCloseSwapServiceStEth = address(new AmmCloseSwapServiceStEthBaseV2(stEthConfig, iporOracleProxy)); } function _createNewSpreadForStEth() private { diff --git a/test/iporOracle/IporOracle.t.sol b/test/iporOracle/IporOracle.t.sol index e44c8303d..8ab44cd12 100644 --- a/test/iporOracle/IporOracle.t.sol +++ b/test/iporOracle/IporOracle.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "../../contracts/oracles/IporOracle.sol"; import "../mocks/tokens/MockTestnetToken.sol"; diff --git a/test/iporOracle/IporOracleStEth.t.sol b/test/iporOracle/IporOracleStEth.t.sol index f73b61be4..b736eb532 100644 --- a/test/iporOracle/IporOracleStEth.t.sol +++ b/test/iporOracle/IporOracleStEth.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "../../contracts/oracles/IporOracle.sol"; -import {TestCommons} from "../TestCommons.sol"; +import {TestCommons} from "../../test/TestCommons.sol"; contract IporOracleStEth is TestCommons { address public constant owner = 0xD92E9F039E4189c342b4067CC61f5d063960D248; @@ -40,7 +40,9 @@ contract IporOracleStEth is TestCommons { ) ); vm.prank(oracleUpdater); - IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice(getIndexToUpdateAndQuasiIbtPrice(stETH, 1e18, block.timestamp - 1, 1e18)); + IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice( + getIndexToUpdateAndQuasiIbtPrice(stETH, 1e18, block.timestamp - 1, 1e18) + ); } function testShouldRevertWhenCallUpdateIndexAndQuasiIbtPriceWithUpdateTimestampFromFuture() external { @@ -54,7 +56,9 @@ contract IporOracleStEth is TestCommons { "updateIndexAndQuasiIbtPrice" ) ); - IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice(getIndexToUpdateAndQuasiIbtPrice(stETH, 1e18, block.timestamp + 1, 1e18)); + IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice( + getIndexToUpdateAndQuasiIbtPrice(stETH, 1e18, block.timestamp + 1, 1e18) + ); } function testShouldRevertWhenIndexValueToBig() external { @@ -63,8 +67,10 @@ contract IporOracleStEth is TestCommons { // when vm.prank(oracleUpdater); - vm.expectRevert(stdError.arithmeticError); - IporOracle(iporOracleProxy).updateIndexes(getIndexToUpdateAndQuasiIbtPrice(stETH, type(uint64).max + 1, block.timestamp - 1, 1e18)); + vm.expectRevert("SafeCast: value doesn't fit in 64 bits"); + IporOracle(iporOracleProxy).updateIndexes( + getIndexToUpdateAndQuasiIbtPrice(stETH, uint256(type(uint64).max) + 1, block.timestamp - 1, 1e18) + ); } function testShouldRevertWhenNewQuasiIbtPriceToBig() external { @@ -73,13 +79,15 @@ contract IporOracleStEth is TestCommons { // when vm.prank(oracleUpdater); - vm.expectRevert(stdError.arithmeticError); - IporOracle(iporOracleProxy).updateIndexes(getIndexToUpdateAndQuasiIbtPrice( - stETH, - type(uint64).max, - block.timestamp - 1, - type(uint128).max + 1 - )); + vm.expectRevert("SafeCast: value doesn't fit in 128 bits"); + IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice( + getIndexToUpdateAndQuasiIbtPrice( + stETH, + type(uint64).max, + block.timestamp - 1, + uint256(type(uint128).max) + 1 + ) + ); } function testShouldUpdateIndex() external { @@ -92,14 +100,16 @@ contract IporOracleStEth is TestCommons { //when vm.prank(oracleUpdater); - IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice(getIndexToUpdateAndQuasiIbtPrice(stETH, 12e16, block.timestamp - 100, 123e16)); + IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice( + getIndexToUpdateAndQuasiIbtPrice(stETH, 12e16, block.timestamp - 100, 123e16) + ); //then (uint256 indexValueAfter, uint256 ibtPriceAfter, uint256 lastUpdateTimestampAfter) = IporOracle(iporOracleProxy) .getIndex(stETH); - console2.log("block.timestamp: ", block.timestamp); + console2.log("block.timestamp: ", block.timestamp); assertEq(indexValueAfter, 12e16); -// assertEq(ibtPriceAfter, 1000000039003044901); + // assertEq(ibtPriceAfter, 1000000039003044901); assertEq(lastUpdateTimestampAfter, block.timestamp - 100); assertEq(indexValueBefore, 0); assertEq(ibtPriceBefore, 1e18); @@ -118,6 +128,8 @@ contract IporOracleStEth is TestCommons { vm.prank(oracleUpdater); vm.expectEmit(true, true, true, true); emit IporIndexUpdate(stETH, 12e16, 123e16, block.timestamp - 100); - IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice(getIndexToUpdateAndQuasiIbtPrice(stETH, 12e16, block.timestamp - 100, 123e16)); + IporOracle(iporOracleProxy).updateIndexesAndQuasiIbtPrice( + getIndexToUpdateAndQuasiIbtPrice(stETH, 12e16, block.timestamp - 100, 123e16) + ); } } diff --git a/test/libraries/math/IporMath.t.sol b/test/libraries/math/IporMath.t.sol index cbe5fae15..03f2e5432 100644 --- a/test/libraries/math/IporMath.t.sol +++ b/test/libraries/math/IporMath.t.sol @@ -4,9 +4,29 @@ pragma solidity 0.8.26; import "forge-std/Test.sol"; import "contracts/libraries/math/IporMath.sol"; +/// @dev Wrapper contract to expose IporMath internal functions as external for testing reverts +contract IporMathWrapper { + function division(uint256 x, uint256 y) external pure returns (uint256) { + return IporMath.division(x, y); + } + + function divisionInt(int256 x, int256 y) external pure returns (int256) { + return IporMath.divisionInt(x, y); + } + + function divisionWithoutRound(uint256 x, uint256 y) external pure returns (uint256) { + return IporMath.divisionWithoutRound(x, y); + } +} + contract IporMathTest is Test { + IporMathWrapper private wrapper; uint256 public constant N1__0_18DEC = 1e18; + function setUp() public { + wrapper = new IporMathWrapper(); + } + function testShouldDivide() public { assertDivision(0, 1, 0); assertDivision(1, 3, 0); @@ -26,7 +46,7 @@ contract IporMathTest is Test { assertDivision(20, 10, 2); vm.expectRevert(); - assertDivision(1, 0, 0); + wrapper.division(1, 0); } function testShouldDivideInt() public { @@ -51,11 +71,11 @@ contract IporMathTest is Test { assertDivisionInt(20, 10, 2); vm.expectRevert(); - assertDivisionInt(1, 0, 0); + wrapper.divisionInt(1, 0); vm.expectRevert(); - assertDivisionInt(-1, 0, 0); + wrapper.divisionInt(-1, 0); vm.expectRevert(); - assertDivisionInt(0, 0, 0); + wrapper.divisionInt(0, 0); } function testShouldDivideWithoutRound() public { @@ -77,7 +97,7 @@ contract IporMathTest is Test { assertDivisionWithoutRound(20, 10, 2); vm.expectRevert(); - assertDivisionWithoutRound(1, 0, 0); + wrapper.divisionWithoutRound(1, 0); } function testShouldConvertWadToAssetDecimalsWithoutRound() public { @@ -233,11 +253,11 @@ contract IporMathTest is Test { assertEq(IporMath.divisionInt(20, -10), -2); vm.expectRevert(); - IporMath.divisionInt(1, 0); + wrapper.divisionInt(1, 0); vm.expectRevert(); - IporMath.divisionInt(-1, 0); + wrapper.divisionInt(-1, 0); vm.expectRevert(); - IporMath.divisionInt(0, 0); + wrapper.divisionInt(0, 0); } function assertDivision(uint256 x, uint256 y, uint256 z) internal { diff --git a/test/mocks/Multicall2.sol b/test/mocks/Multicall2.sol index e2beac17f..266e66c35 100644 --- a/test/mocks/Multicall2.sol +++ b/test/mocks/Multicall2.sol @@ -54,7 +54,7 @@ contract Multicall2 { } function getCurrentBlockDifficulty() public view returns (uint256 difficulty) { - difficulty = block.difficulty; + difficulty = block.prevrandao; } function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) { diff --git a/test/mocks/Multicall3.sol b/test/mocks/Multicall3.sol index 5cf897d73..f5c1e1412 100644 --- a/test/mocks/Multicall3.sol +++ b/test/mocks/Multicall3.sol @@ -43,12 +43,14 @@ contract Multicall3 { uint256 length = calls.length; returnData = new bytes[](length); Call calldata call; - for (uint256 i = 0; i < length;) { + for (uint256 i = 0; i < length; ) { bool success; call = calls[i]; (success, returnData[i]) = call.target.call(call.callData); require(success, "Multicall3: call failed"); - unchecked { ++i; } + unchecked { + ++i; + } } } @@ -57,16 +59,21 @@ contract Multicall3 { /// @param requireSuccess If true, require all calls to succeed /// @param calls An array of Call structs /// @return returnData An array of Result structs - function tryAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (Result[] memory returnData) { + function tryAggregate( + bool requireSuccess, + Call[] calldata calls + ) public payable returns (Result[] memory returnData) { uint256 length = calls.length; returnData = new Result[](length); Call calldata call; - for (uint256 i = 0; i < length;) { + for (uint256 i = 0; i < length; ) { Result memory result = returnData[i]; call = calls[i]; (result.success, result.returnData) = call.target.call(call.callData); if (requireSuccess) require(result.success, "Multicall3: call failed"); - unchecked { ++i; } + unchecked { + ++i; + } } } @@ -76,7 +83,10 @@ contract Multicall3 { /// @return blockNumber The block number where the calls were executed /// @return blockHash The hash of the block where the calls were executed /// @return returnData An array of Result structs - function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { + function tryBlockAndAggregate( + bool requireSuccess, + Call[] calldata calls + ) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { blockNumber = block.number; blockHash = blockhash(block.number); returnData = tryAggregate(requireSuccess, calls); @@ -88,7 +98,9 @@ contract Multicall3 { /// @return blockNumber The block number where the calls were executed /// @return blockHash The hash of the block where the calls were executed /// @return returnData An array of Result structs - function blockAndAggregate(Call[] calldata calls) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { + function blockAndAggregate( + Call[] calldata calls + ) public payable returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData) { (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls); } @@ -99,26 +111,28 @@ contract Multicall3 { uint256 length = calls.length; returnData = new Result[](length); Call3 calldata calli; - for (uint256 i = 0; i < length;) { + for (uint256 i = 0; i < length; ) { Result memory result = returnData[i]; calli = calls[i]; (result.success, result.returnData) = calli.target.call(calli.callData); assembly { - // Revert if the call fails and failure is not allowed - // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` + // Revert if the call fails and failure is not allowed + // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { - // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) + // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) - // set data offset + // set data offset mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) - // set length of revert string + // set length of revert string mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) - // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) + // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) revert(0x00, 0x64) } } - unchecked { ++i; } + unchecked { + ++i; + } } } @@ -131,30 +145,34 @@ contract Multicall3 { uint256 length = calls.length; returnData = new Result[](length); Call3Value calldata calli; - for (uint256 i = 0; i < length;) { + for (uint256 i = 0; i < length; ) { Result memory result = returnData[i]; calli = calls[i]; uint256 val = calli.value; // Humanity will be a Type V Kardashev Civilization before this overflows - andreas // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256 - unchecked { valAccumulator += val; } + unchecked { + valAccumulator += val; + } (result.success, result.returnData) = calli.target.call{value: val}(calli.callData); assembly { - // Revert if the call fails and failure is not allowed - // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` + // Revert if the call fails and failure is not allowed + // `allowFailure := calldataload(add(calli, 0x20))` and `success := mload(result)` if iszero(or(calldataload(add(calli, 0x20)), mload(result))) { - // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) + // set "Error(string)" signature: bytes32(bytes4(keccak256("Error(string)"))) mstore(0x00, 0x08c379a000000000000000000000000000000000000000000000000000000000) - // set data offset + // set data offset mstore(0x04, 0x0000000000000000000000000000000000000000000000000000000000000020) - // set length of revert string + // set length of revert string mstore(0x24, 0x0000000000000000000000000000000000000000000000000000000000000017) - // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) + // set revert string: bytes32(abi.encodePacked("Multicall3: call failed")) mstore(0x44, 0x4d756c746963616c6c333a2063616c6c206661696c6564000000000000000000) revert(0x00, 0x84) } } - unchecked { ++i; } + unchecked { + ++i; + } } // Finally, make sure the msg.value = SUM(call[0...i].value) require(msg.value == valAccumulator, "Multicall3: value mismatch"); @@ -178,7 +196,7 @@ contract Multicall3 { /// @notice Returns the block difficulty function getCurrentBlockDifficulty() public view returns (uint256 difficulty) { - difficulty = block.difficulty; + difficulty = block.prevrandao; } /// @notice Returns the block gas limit @@ -213,4 +231,4 @@ contract Multicall3 { function getChainId() public view returns (uint256 chainid) { chainid = block.chainid; } -} \ No newline at end of file +} diff --git a/test/security/IporOwnable.t.sol b/test/security/IporOwnable.t.sol index b72b9a715..869bc6ed4 100644 --- a/test/security/IporOwnable.t.sol +++ b/test/security/IporOwnable.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../security/IporOwnableInstance.sol"; import "../../contracts/libraries/errors/IporErrors.sol"; diff --git a/test/security/IporOwnableUpgradeable.t.sol b/test/security/IporOwnableUpgradeable.t.sol index 7f243769a..89f5814d5 100644 --- a/test/security/IporOwnableUpgradeable.t.sol +++ b/test/security/IporOwnableUpgradeable.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../security/IporOwnableUpgradeableInstance.sol"; import "../../contracts/libraries/errors/IporErrors.sol"; diff --git a/test/spread/CalculateWeightedNotionalLibsTest.t.sol b/test/spread/CalculateWeightedNotionalLibsTest.t.sol index 5c07cca55..0e4055029 100644 --- a/test/spread/CalculateWeightedNotionalLibsTest.t.sol +++ b/test/spread/CalculateWeightedNotionalLibsTest.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import "../../contracts/amm/spread/CalculateTimeWeightedNotionalLibs.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; contract CalculateWeightedNotionalLibsTest is TestCommons { SpreadStorageLibs.StorageId internal _storageIdIterationItem; diff --git a/test/spread/SpreadAccessControl.t.sol b/test/spread/SpreadAccessControl.t.sol index 81c0be82a..f88d5669b 100644 --- a/test/spread/SpreadAccessControl.t.sol +++ b/test/spread/SpreadAccessControl.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "./SpreadTestSystem.sol"; contract SpreadAccessControlTest is TestCommons { diff --git a/test/spread/SpreadBaseTestUtils.sol b/test/spread/SpreadBaseTestUtils.sol index 595a3c97b..fefad40c2 100644 --- a/test/spread/SpreadBaseTestUtils.sol +++ b/test/spread/SpreadBaseTestUtils.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; abstract contract SpreadBaseTestUtils is TestCommons { address internal _dai; diff --git a/test/spread/SpreadRouter.t.sol b/test/spread/SpreadRouter.t.sol index d4d3f1b09..67dec2810 100644 --- a/test/spread/SpreadRouter.t.sol +++ b/test/spread/SpreadRouter.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../../contracts/amm/spread/SpreadRouter.sol"; import "./MockSpreadServices.sol"; import "../../contracts/interfaces/types/IporTypes.sol"; diff --git a/test/spread/SpreadSmoke.t.sol b/test/spread/SpreadSmoke.t.sol index ae9ec9604..6e087d560 100644 --- a/test/spread/SpreadSmoke.t.sol +++ b/test/spread/SpreadSmoke.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "./SpreadTestSystem.sol"; contract SpreadSmokeTest is TestCommons { diff --git a/test/spread/SpreadStorageTest.t.sol b/test/spread/SpreadStorageTest.t.sol index d98d2624d..3ea8f515f 100644 --- a/test/spread/SpreadStorageTest.t.sol +++ b/test/spread/SpreadStorageTest.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/utils/math/SafeCast.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "../../contracts/amm/spread/SpreadTypes.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "./MockSpreadStorage.sol"; diff --git a/test/spread/SpreadTestSystem.sol b/test/spread/SpreadTestSystem.sol index 675c85296..84ecaa471 100644 --- a/test/spread/SpreadTestSystem.sol +++ b/test/spread/SpreadTestSystem.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../../contracts/amm/spread/Spread28Days.sol"; import "../../contracts/amm/spread/Spread60Days.sol"; import "../../contracts/amm/spread/Spread90Days.sol"; diff --git a/test/spreadBaseV1/CalculateWeightedNotionalLibsBaseV1Test.t.sol b/test/spreadBaseV1/CalculateWeightedNotionalLibsBaseV1Test.t.sol index 602d49291..e3f6b34c8 100644 --- a/test/spreadBaseV1/CalculateWeightedNotionalLibsBaseV1Test.t.sol +++ b/test/spreadBaseV1/CalculateWeightedNotionalLibsBaseV1Test.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import "../../contracts/base/spread/CalculateTimeWeightedNotionalLibsBaseV1.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; contract CalculateWeightedNotionalLibsBaseV1Test is TestCommons { SpreadStorageLibsBaseV1.StorageId internal _storageIdIterationItem; diff --git a/test/tokens/IpToken.t.sol b/test/tokens/IpToken.t.sol index c9db74b87..578103423 100644 --- a/test/tokens/IpToken.t.sol +++ b/test/tokens/IpToken.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.26; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../../contracts/tokens/IpToken.sol"; import "../utils/TestConstants.sol"; diff --git a/test/tokens/IporToken.t.sol b/test/tokens/IporToken.t.sol index 630ca24fd..57af11eb7 100644 --- a/test/tokens/IporToken.t.sol +++ b/test/tokens/IporToken.t.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import "../../contracts/tokens/IporToken.sol"; -import "../TestCommons.sol"; +import "../../test/TestCommons.sol"; import "../utils/TestConstants.sol"; contract IporTokenTest is TestCommons { diff --git a/test/utils/builder/BuilderUtils.sol b/test/utils/builder/BuilderUtils.sol index 8387e4d6d..c013c9e73 100644 --- a/test/utils/builder/BuilderUtils.sol +++ b/test/utils/builder/BuilderUtils.sol @@ -8,7 +8,7 @@ import "../../mocks/MockIporWeighted.sol"; import "../../../contracts/amm/AmmStorage.sol"; import "../../../contracts/amm/AmmTreasury.sol"; import "../../../contracts/amm/spread/SpreadRouter.sol"; -import "../../../contracts/chains/ethereum/router/IporProtocolRouter.sol"; +import "../../../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; import "../../../contracts/interfaces/IAmmOpenSwapLens.sol"; import "../../../contracts/interfaces/IAmmCloseSwapLens.sol"; import "../../mocks/tokens/MockTestnetToken.sol"; @@ -16,7 +16,7 @@ import "../../mocks/tokens/MockTestnetToken.sol"; contract BuilderUtils { struct IporProtocol { - IporProtocolRouter router; + IporProtocolRouterEthereum router; IAmmSwapsLens ammSwapsLens; IAmmPoolsService ammPoolsService; IAmmPoolsLens ammPoolsLens; diff --git a/test/utils/builder/IporProtocolRouterBuilder.sol b/test/utils/builder/IporProtocolRouterBuilder.sol index da05019b3..266e72fa7 100644 --- a/test/utils/builder/IporProtocolRouterBuilder.sol +++ b/test/utils/builder/IporProtocolRouterBuilder.sol @@ -4,29 +4,28 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "forge-std/Test.sol"; import "../../mocks/EmptyRouterImplementation.sol"; -import "../../../contracts/chains/ethereum/router/IporProtocolRouter.sol"; +import "../../../contracts/chains/ethereum/router/IporProtocolRouterEthereum.sol"; contract IporProtocolRouterBuilder is Test { struct BuilderData { address ammSwapsLens; address ammPoolsLens; - address ammPoolsLensStEth; + address ammPoolsLensBaseV1; address assetManagementLens; address ammOpenSwapService; - address ammOpenSwapServiceStEth; address ammCloseSwapServiceUsdt; address ammCloseSwapServiceUsdc; address ammCloseSwapServiceDai; - address ammCloseSwapServiceStEth; address ammCloseSwapLens; - address ammCloseSwapLensStEth; address ammPoolsService; - address ammPoolsServiceStEth; address ammGovernanceService; address liquidityMiningLens; address powerTokenLens; address flowService; address stakeService; + address stEth; + address weEth; + address usdm; } BuilderData private builderData; @@ -57,11 +56,6 @@ contract IporProtocolRouterBuilder is Test { return this; } - function withAmmOpenSwapServiceStEth(address ammOpenSwapServiceStEth) public returns (IporProtocolRouterBuilder) { - builderData.ammOpenSwapServiceStEth = ammOpenSwapServiceStEth; - return this; - } - function withAmmCloseSwapServiceUsdt(address ammCloseSwapService) public returns (IporProtocolRouterBuilder) { builderData.ammCloseSwapServiceUsdt = ammCloseSwapService; return this; @@ -92,48 +86,50 @@ contract IporProtocolRouterBuilder is Test { return this; } - function buildEmptyProxy() public returns (IporProtocolRouter) { + function withUsdm(address usdm) public returns (IporProtocolRouterBuilder) { + builderData.usdm = usdm; + return this; + } + + function buildEmptyProxy() public returns (IporProtocolRouterEthereum) { vm.startPrank(_owner); address payable proxy = _constructProxy(new EmptyRouterImplementation()); - IporProtocolRouter iporProtocolRouter = IporProtocolRouter(proxy); + IporProtocolRouterEthereum iporProtocolRouter = IporProtocolRouterEthereum(proxy); vm.stopPrank(); delete builderData; return iporProtocolRouter; } - function build() public returns (IporProtocolRouter) { + function build() public returns (IporProtocolRouterEthereum) { vm.startPrank(_owner); - IporProtocolRouter.DeployedContracts memory deployedContracts = IporProtocolRouter.DeployedContracts({ - ammSwapsLens: builderData.ammSwapsLens, - ammPoolsLens: builderData.ammPoolsLens, - assetManagementLens: builderData.assetManagementLens, - ammOpenSwapService: builderData.ammOpenSwapService, - ammOpenSwapServiceStEth: builderData.ammOpenSwapServiceStEth, - ammCloseSwapServiceUsdt: builderData.ammCloseSwapServiceUsdt, - ammCloseSwapServiceUsdc: builderData.ammCloseSwapServiceUsdc, - ammCloseSwapServiceDai: builderData.ammCloseSwapServiceDai, - ammCloseSwapLens: builderData.ammCloseSwapLens, - ammCloseSwapServiceStEth: builderData.ammCloseSwapServiceStEth, - ammPoolsService: builderData.ammPoolsService, - ammGovernanceService: builderData.ammGovernanceService, - liquidityMiningLens: builderData.liquidityMiningLens, - powerTokenLens: builderData.powerTokenLens, - flowService: builderData.flowService, - stakeService: builderData.stakeService, - ammPoolsServiceStEth: builderData.ammPoolsServiceStEth, - ammPoolsLensStEth: builderData.ammPoolsLensStEth, - ammPoolsServiceWeEth: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, // TODO: fix address if needed - ammPoolsLensWeEth: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, // TODO: fix address if needed - ammPoolsServiceUsdm: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, // TODO: fix address if needed - ammPoolsLensUsdm: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 // TODO: fix address if needed - - - }); - - address payable proxy = _constructProxy(new IporProtocolRouter(deployedContracts)); - IporProtocolRouter iporProtocolRouter = IporProtocolRouter(proxy); + IporProtocolRouterEthereum.DeployedContracts memory deployedContracts = IporProtocolRouterEthereum + .DeployedContracts({ + ammSwapsLens: builderData.ammSwapsLens, + ammPoolsLens: builderData.ammPoolsLens, + ammPoolsLensBaseV1: builderData.ammPoolsLensBaseV1 != address(0) + ? builderData.ammPoolsLensBaseV1 + : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, + assetManagementLens: builderData.assetManagementLens, + ammOpenSwapService: builderData.ammOpenSwapService, + ammCloseSwapServiceUsdt: builderData.ammCloseSwapServiceUsdt, + ammCloseSwapServiceUsdc: builderData.ammCloseSwapServiceUsdc, + ammCloseSwapServiceDai: builderData.ammCloseSwapServiceDai, + ammCloseSwapLens: builderData.ammCloseSwapLens, + ammPoolsService: builderData.ammPoolsService, + ammGovernanceService: builderData.ammGovernanceService, + liquidityMiningLens: builderData.liquidityMiningLens, + powerTokenLens: builderData.powerTokenLens, + flowService: builderData.flowService, + stakeService: builderData.stakeService, + stEth: builderData.stEth != address(0) ? builderData.stEth : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, + weEth: builderData.weEth != address(0) ? builderData.weEth : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, + usdm: builderData.usdm != address(0) ? builderData.usdm : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + }); + + address payable proxy = _constructProxy(new IporProtocolRouterEthereum(deployedContracts)); + IporProtocolRouterEthereum iporProtocolRouter = IporProtocolRouterEthereum(proxy); vm.stopPrank(); delete builderData; @@ -143,33 +139,32 @@ contract IporProtocolRouterBuilder is Test { function upgrade(address payable routerAddress) public { vm.startPrank(_owner); - IporProtocolRouter.DeployedContracts memory deployedContracts = IporProtocolRouter.DeployedContracts({ - ammSwapsLens: builderData.ammSwapsLens, - ammPoolsLens: builderData.ammPoolsLens, - ammPoolsLensStEth: builderData.ammPoolsLensStEth, - assetManagementLens: builderData.assetManagementLens, - ammOpenSwapService: builderData.ammOpenSwapService, - ammOpenSwapServiceStEth: builderData.ammOpenSwapServiceStEth, - ammCloseSwapServiceUsdt: builderData.ammCloseSwapServiceUsdt, - ammCloseSwapServiceUsdc: builderData.ammCloseSwapServiceUsdc, - ammCloseSwapServiceDai: builderData.ammCloseSwapServiceDai, - ammCloseSwapLens: builderData.ammCloseSwapLens, - ammCloseSwapServiceStEth: builderData.ammCloseSwapServiceStEth, - ammPoolsService: builderData.ammPoolsService, - ammPoolsServiceStEth: builderData.ammPoolsServiceStEth, - ammGovernanceService: builderData.ammGovernanceService, - liquidityMiningLens: builderData.liquidityMiningLens, - powerTokenLens: builderData.powerTokenLens, - flowService: builderData.flowService, - stakeService: builderData.stakeService, - ammPoolsServiceWeEth: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, // TODO: fix address if needed - ammPoolsLensWeEth: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, // TODO: fix address if needed - ammPoolsServiceUsdm: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, // TODO: fix address if needed - ammPoolsLensUsdm: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 // TODO: fix address if needed - }); - - IporProtocolRouter router = IporProtocolRouter(routerAddress); - router.upgradeTo(address(new IporProtocolRouter(deployedContracts))); + IporProtocolRouterEthereum.DeployedContracts memory deployedContracts = IporProtocolRouterEthereum + .DeployedContracts({ + ammSwapsLens: builderData.ammSwapsLens, + ammPoolsLens: builderData.ammPoolsLens, + ammPoolsLensBaseV1: builderData.ammPoolsLensBaseV1 != address(0) + ? builderData.ammPoolsLensBaseV1 + : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, + assetManagementLens: builderData.assetManagementLens, + ammOpenSwapService: builderData.ammOpenSwapService, + ammCloseSwapServiceUsdt: builderData.ammCloseSwapServiceUsdt, + ammCloseSwapServiceUsdc: builderData.ammCloseSwapServiceUsdc, + ammCloseSwapServiceDai: builderData.ammCloseSwapServiceDai, + ammCloseSwapLens: builderData.ammCloseSwapLens, + ammPoolsService: builderData.ammPoolsService, + ammGovernanceService: builderData.ammGovernanceService, + liquidityMiningLens: builderData.liquidityMiningLens, + powerTokenLens: builderData.powerTokenLens, + flowService: builderData.flowService, + stakeService: builderData.stakeService, + stEth: builderData.stEth != address(0) ? builderData.stEth : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, + weEth: builderData.weEth != address(0) ? builderData.weEth : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, + usdm: builderData.usdm != address(0) ? builderData.usdm : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + }); + + IporProtocolRouterEthereum router = IporProtocolRouterEthereum(routerAddress); + router.upgradeTo(address(new IporProtocolRouterEthereum(deployedContracts))); vm.stopPrank(); } @@ -178,7 +173,7 @@ contract IporProtocolRouterBuilder is Test { proxy = payable(address(new ERC1967Proxy(address(impl), abi.encodeWithSignature("initialize(bool)", false)))); } - function _constructProxy(IporProtocolRouter impl) internal returns (address payable proxy) { + function _constructProxy(IporProtocolRouterEthereum impl) internal returns (address payable proxy) { proxy = payable(address(new ERC1967Proxy(address(impl), abi.encodeWithSignature("initialize(bool)", false)))); } } diff --git a/test/utils/factory/IporProtocolFactory.sol b/test/utils/factory/IporProtocolFactory.sol index 1d87f1870..5b08d6b78 100644 --- a/test/utils/factory/IporProtocolFactory.sol +++ b/test/utils/factory/IporProtocolFactory.sol @@ -23,17 +23,20 @@ import "../../../contracts/interfaces/IPowerTokenLens.sol"; import "../../../contracts/interfaces/ILiquidityMiningLens.sol"; import "../../../contracts/interfaces/IPowerTokenFlowsService.sol"; import "../../../contracts/interfaces/IPowerTokenStakeService.sol"; -import "../../../contracts/chains/ethereum/amm-commons/AmmSwapsLens.sol"; -import "../../../contracts/amm/AmmPoolsLens.sol"; +import "../../../contracts/base/amm/services/AmmSwapsLensBaseV1.sol"; +import "../../../contracts/base/amm/services/AmmPoolsLensBaseV1.sol"; import "../../../contracts/amm/AssetManagementLens.sol"; import "../../../contracts/amm/AmmOpenSwapService.sol"; import "../../../contracts/amm/AmmCloseSwapServiceUsdt.sol"; import "../../../contracts/amm/AmmCloseSwapServiceUsdc.sol"; import "../../../contracts/amm/AmmCloseSwapServiceDai.sol"; +import "../../../contracts/base/amm/services/AmmCloseSwapLensBaseV1.sol"; import "../../../contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol"; import "../../../contracts/amm/AmmPoolsService.sol"; -import "../../../contracts/chains/ethereum/amm-commons/AmmGovernanceService.sol"; +import "../../../contracts/base/amm/services/AmmGovernanceServiceBaseV1.sol"; +import "../../../contracts/base/interfaces/IAmmGovernanceServiceBaseV1.sol"; +import "../../../contracts/base/libraries/StorageLibBaseV1.sol"; import "../../mocks/EmptyImplementation.sol"; import "../builder/PowerTokenLensBuilder.sol"; import "../builder/LiquidityMiningLensBuilder.sol"; @@ -41,10 +44,11 @@ import "../builder/PowerTokenFlowsServiceBuilder.sol"; import "../builder/PowerTokenStakeServiceBuilder.sol"; import {MockPlasmaVault} from "../../mocks/tokens/MockPlasmaVault.sol"; - +import {AmmSwapsLens} from "../../../contracts/chains/ethereum/amm-commons/AmmSwapsLens.sol"; +import {AmmPoolsLens} from "../../../contracts/amm/AmmPoolsLens.sol"; contract IporProtocolFactory is Test { struct Amm { - IporProtocolRouter router; + IporProtocolRouterEthereum router; SpreadRouter spreadRouter; IporOracle iporOracle; MockIporWeighted iporWeighted; @@ -109,7 +113,6 @@ contract IporProtocolFactory is Test { address internal _fakeAsset = address(0x777777777); address internal _fakeContract = address(new EmptyImplementation(_fakeAsset)); - address internal _owner; uint256 public messageSignerPrivateKey; address public messageSignerAddress; @@ -167,8 +170,7 @@ contract IporProtocolFactory is Test { amm.usdc.assetManagement = new MockPlasmaVault(IERC20(amm.usdc.asset), "ipUSDCfusion", "ipUSDCfusion"); amm.dai.assetManagement = new MockPlasmaVault(IERC20(amm.dai.asset), "ipDAIfusion", "ipDAIfusion"); - - address[] memory assets = new address[](5); + address[] memory assets = new address[](5); assets[0] = address(amm.dai.asset); assets[1] = address(amm.usdt.asset); assets[2] = address(amm.usdc.asset); @@ -267,28 +269,28 @@ contract IporProtocolFactory is Test { amm.usdm.spreadRouter = amm.spreadRouter; _ammTreasuryBuilder - .withAsset(address(amm.usdt.asset)) - .withAmmStorage(address(amm.usdt.ammStorage)) - .withAssetManagement(address(amm.usdt.assetManagement)) - .withIporProtocolRouter(address(amm.router)) - .withAmmTreasuryProxyAddress(address(amm.usdt.ammTreasury)) - .upgrade(); + .withAsset(address(amm.usdt.asset)) + .withAmmStorage(address(amm.usdt.ammStorage)) + .withAssetManagement(address(amm.usdt.assetManagement)) + .withIporProtocolRouter(address(amm.router)) + .withAmmTreasuryProxyAddress(address(amm.usdt.ammTreasury)) + .upgrade(); _ammTreasuryBuilder - .withAsset(address(amm.usdc.asset)) - .withAmmStorage(address(amm.usdc.ammStorage)) - .withAssetManagement(address(amm.usdc.assetManagement)) - .withIporProtocolRouter(address(amm.router)) - .withAmmTreasuryProxyAddress(address(amm.usdc.ammTreasury)) - .upgrade(); + .withAsset(address(amm.usdc.asset)) + .withAmmStorage(address(amm.usdc.ammStorage)) + .withAssetManagement(address(amm.usdc.assetManagement)) + .withIporProtocolRouter(address(amm.router)) + .withAmmTreasuryProxyAddress(address(amm.usdc.ammTreasury)) + .upgrade(); _ammTreasuryBuilder - .withAsset(address(amm.dai.asset)) - .withAmmStorage(address(amm.dai.ammStorage)) - .withAssetManagement(address(amm.dai.assetManagement)) - .withIporProtocolRouter(address(amm.router)) - .withAmmTreasuryProxyAddress(address(amm.dai.ammTreasury)) - .upgrade(); + .withAsset(address(amm.dai.asset)) + .withAmmStorage(address(amm.dai.ammStorage)) + .withAssetManagement(address(amm.dai.assetManagement)) + .withIporProtocolRouter(address(amm.router)) + .withAmmTreasuryProxyAddress(address(amm.dai.ammTreasury)) + .upgrade(); amm.router = _getFullIporProtocolRouterInstance(amm, cfg); @@ -375,12 +377,12 @@ contract IporProtocolFactory is Test { iporProtocol.spreadRouter = _spreadRouterBuilder.build(); _ammTreasuryBuilder - .withAsset(address(iporProtocol.asset)) - .withAmmStorage(address(iporProtocol.ammStorage)) - .withAssetManagement(address(iporProtocol.assetManagement)) - .withIporProtocolRouter(address(iporProtocol.router)) - .withAmmTreasuryProxyAddress(address(iporProtocol.ammTreasury)) - .upgrade(); + .withAsset(address(iporProtocol.asset)) + .withAmmStorage(address(iporProtocol.ammStorage)) + .withAssetManagement(address(iporProtocol.assetManagement)) + .withIporProtocolRouter(address(iporProtocol.router)) + .withAmmTreasuryProxyAddress(address(iporProtocol.ammTreasury)) + .upgrade(); iporProtocol.router = _getUsdtIporProtocolRouterInstance(iporProtocol, cfg); @@ -396,6 +398,8 @@ contract IporProtocolFactory is Test { iporProtocol.ammGovernanceService = IAmmGovernanceService(address(iporProtocol.router)); iporProtocol.ammGovernanceLens = IAmmGovernanceLens(address(iporProtocol.router)); + // Setup is now done inside _getUsdtIporProtocolRouterInstance / _getUsdcIporProtocolRouterInstance + vm.startPrank(address(_owner)); iporProtocol.ammTreasury.grantMaxAllowanceForSpender(address(iporProtocol.assetManagement)); @@ -471,12 +475,12 @@ contract IporProtocolFactory is Test { iporProtocol.spreadRouter = _spreadRouterBuilder.build(); _ammTreasuryBuilder - .withAsset(address(iporProtocol.asset)) - .withAmmStorage(address(iporProtocol.ammStorage)) - .withAssetManagement(address(iporProtocol.assetManagement)) - .withIporProtocolRouter(address(iporProtocol.router)) - .withAmmTreasuryProxyAddress(address(iporProtocol.ammTreasury)) - .upgrade(); + .withAsset(address(iporProtocol.asset)) + .withAmmStorage(address(iporProtocol.ammStorage)) + .withAssetManagement(address(iporProtocol.assetManagement)) + .withIporProtocolRouter(address(iporProtocol.router)) + .withAmmTreasuryProxyAddress(address(iporProtocol.ammTreasury)) + .upgrade(); iporProtocol.router = _getUsdcIporProtocolRouterInstance(iporProtocol, cfg); @@ -492,6 +496,8 @@ contract IporProtocolFactory is Test { iporProtocol.ammGovernanceService = IAmmGovernanceService(address(iporProtocol.router)); iporProtocol.ammGovernanceLens = IAmmGovernanceLens(address(iporProtocol.router)); + // Setup is now done inside _getUsdtIporProtocolRouterInstance / _getUsdcIporProtocolRouterInstance + vm.startPrank(address(_owner)); iporProtocol.ammTreasury.grantMaxAllowanceForSpender(address(iporProtocol.assetManagement)); @@ -568,12 +574,12 @@ contract IporProtocolFactory is Test { iporProtocol.spreadRouter = _spreadRouterBuilder.build(); _ammTreasuryBuilder - .withAsset(address(iporProtocol.asset)) - .withAmmStorage(address(iporProtocol.ammStorage)) - .withAssetManagement(address(iporProtocol.assetManagement)) - .withIporProtocolRouter(address(iporProtocol.router)) - .withAmmTreasuryProxyAddress(address(iporProtocol.ammTreasury)) - .upgrade(); + .withAsset(address(iporProtocol.asset)) + .withAmmStorage(address(iporProtocol.ammStorage)) + .withAssetManagement(address(iporProtocol.assetManagement)) + .withIporProtocolRouter(address(iporProtocol.router)) + .withAmmTreasuryProxyAddress(address(iporProtocol.ammTreasury)) + .upgrade(); iporProtocol.router = _getDaiIporProtocolRouterInstance(iporProtocol, cfg); iporProtocol.ammSwapsLens = IAmmSwapsLens(address(iporProtocol.router)); @@ -588,6 +594,8 @@ contract IporProtocolFactory is Test { iporProtocol.ammGovernanceService = IAmmGovernanceService(address(iporProtocol.router)); iporProtocol.ammGovernanceLens = IAmmGovernanceLens(address(iporProtocol.router)); + // Setup is now done inside _getDaiIporProtocolRouterInstance + vm.startPrank(address(_owner)); iporProtocol.ammTreasury.grantMaxAllowanceForSpender(address(iporProtocol.assetManagement)); @@ -610,12 +618,12 @@ contract IporProtocolFactory is Test { function _getFullIporProtocolRouterInstance( Amm memory amm, AmmConfig memory cfg - ) public returns (IporProtocolRouter) { + ) public returns (IporProtocolRouterEthereum) { if (address(amm.router) == address(0)) { amm.router = _iporProtocolRouterBuilder.buildEmptyProxy(); } - IporProtocolRouter.DeployedContracts memory deployerContracts; + IporProtocolRouterEthereum.DeployedContracts memory deployerContracts; deployerContracts.ammSwapsLens = address( new AmmSwapsLens( @@ -678,6 +686,8 @@ contract IporProtocolFactory is Test { ) ); + deployerContracts.ammPoolsLensBaseV1 = address(new AmmPoolsLensBaseV1({iporOracle_: address(amm.iporOracle)})); + deployerContracts.assetManagementLens = address( new AssetManagementLens( IAssetManagementLens.AssetManagementConfiguration({ @@ -774,17 +784,9 @@ contract IporProtocolFactory is Test { deployerContracts.ammCloseSwapLens = address( new AmmCloseSwapLens({ - usdtInput: address(amm.usdt.asset), - usdcInput: address(amm.usdc.asset), - daiInput: address(amm.dai.asset), - stETHInput: _fakeAsset, - iporOracleInput: address(amm.iporOracle), - messageSignerInput: messageSignerAddress, - spreadRouterInput: address(amm.spreadRouter), - closeSwapServiceUsdtInput: deployerContracts.ammCloseSwapServiceUsdt, - closeSwapServiceUsdcInput: deployerContracts.ammCloseSwapServiceUsdc, - closeSwapServiceDaiInput: deployerContracts.ammCloseSwapServiceDai, - closeSwapServiceStEthInput: _fakeContract + iporOracle_: address(amm.iporOracle), + messageSigner_: messageSignerAddress, + spreadRouter_: address(amm.spreadRouter) }) ); @@ -819,68 +821,7 @@ contract IporProtocolFactory is Test { ); deployerContracts.ammGovernanceService = address( - new AmmGovernanceService({ - usdtPoolCfg: _preparePoolCfgForGovernanceService( - address(amm.usdt.asset), - address(amm.usdt.ammTreasury), - address(amm.usdt.ammStorage), - address(amm.usdt.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ), - usdcPoolCfg: _preparePoolCfgForGovernanceService( - address(amm.usdc.asset), - address(amm.usdc.ammTreasury), - address(amm.usdc.ammStorage), - address(amm.usdc.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ), - daiPoolCfg: _preparePoolCfgForGovernanceService( - address(amm.dai.asset), - address(amm.dai.ammTreasury), - address(amm.dai.ammStorage), - address(amm.dai.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ), - stEthPoolCfg: _preparePoolCfgForGovernanceService( - address(amm.stEth.asset), - address(amm.stEth.ammTreasury), - address(amm.stEth.ammStorage), - address(amm.stEth.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ), - weEthPoolCfg: _preparePoolCfgForGovernanceService( - address(amm.stEth.asset), // mock todo: fix if needed - address(amm.stEth.ammTreasury), - address(amm.stEth.ammStorage), - address(amm.stEth.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ), - usdmPoolCfg: _preparePoolCfgForGovernanceService( - address(amm.usdm.asset), // mock todo: fix if needed - address(amm.usdm.ammTreasury), - address(amm.usdm.ammStorage), - address(amm.usdm.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ) - }) + new AmmGovernanceServiceBaseV1() ); deployerContracts.powerTokenLens = address(_powerTokenLensBuilder.build()); @@ -888,19 +829,16 @@ contract IporProtocolFactory is Test { deployerContracts.flowService = address(_powerTokenFlowsServiceBuilder.build()); deployerContracts.stakeService = address(_powerTokenStakeServiceBuilder.build()); - deployerContracts.ammPoolsLensStEth = _fakeContract; - deployerContracts.ammPoolsServiceStEth = _fakeContract; - deployerContracts.ammOpenSwapServiceStEth = _fakeContract; - deployerContracts.ammCloseSwapServiceStEth = _fakeContract; - deployerContracts.ammPoolsLensWeEth = _fakeContract; - deployerContracts.ammPoolsServiceWeEth = _fakeContract; - deployerContracts.ammPoolsLensUsdm = _fakeContract; - deployerContracts.ammPoolsServiceUsdm = _fakeContract; + deployerContracts.stEth = address(amm.stEth.asset); + deployerContracts.weEth = _fakeAsset; + deployerContracts.usdm = _fakeAsset; vm.startPrank(address(_owner)); - IporProtocolRouter(amm.router).upgradeTo(address(new IporProtocolRouter(deployerContracts))); + IporProtocolRouterEthereum(amm.router).upgradeTo(address(new IporProtocolRouterEthereum(deployerContracts))); vm.stopPrank(); + _setupGovernanceServiceAfterRouterUpgrade(amm, cfg, messageSignerAddress); + amm.usdt.ammSwapsLens = IAmmSwapsLens(address(amm.router)); amm.usdt.ammPoolsService = IAmmPoolsService(address(amm.router)); amm.usdt.ammPoolsLens = IAmmPoolsLens(address(amm.router)); @@ -944,17 +882,17 @@ contract IporProtocolFactory is Test { amm.dai.liquidityMiningLens = ILiquidityMiningLens(address(amm.router)); amm.dai.flowService = IPowerTokenFlowsService(address(amm.router)); amm.dai.stakeService = IPowerTokenStakeService(address(amm.router)); - return IporProtocolRouter(amm.router); + return IporProtocolRouterEthereum(amm.router); } function _getUsdtIporProtocolRouterInstance( BuilderUtils.IporProtocol memory iporProtocol, IporProtocolConfig memory cfg - ) public returns (IporProtocolRouter) { + ) public returns (IporProtocolRouterEthereum) { if (address(iporProtocol.router) == address(0)) { iporProtocol.router = _iporProtocolRouterBuilder.buildEmptyProxy(); } - IporProtocolRouter.DeployedContracts memory deployerContracts; + IporProtocolRouterEthereum.DeployedContracts memory deployerContracts; deployerContracts.ammSwapsLens = address( new AmmSwapsLens( @@ -1017,6 +955,10 @@ contract IporProtocolFactory is Test { ) ); + deployerContracts.ammPoolsLensBaseV1 = address( + new AmmPoolsLensBaseV1({iporOracle_: address(iporProtocol.iporOracle)}) + ); + deployerContracts.assetManagementLens = address( new AssetManagementLens( IAssetManagementLens.AssetManagementConfiguration({ @@ -1076,17 +1018,9 @@ contract IporProtocolFactory is Test { deployerContracts.ammCloseSwapLens = address( new AmmCloseSwapLens({ - usdtInput: address(iporProtocol.asset), - usdcInput: _fakeAsset, - daiInput: _fakeAsset, - stETHInput: _fakeAsset, - iporOracleInput: address(iporProtocol.iporOracle), - messageSignerInput: messageSignerAddress, - spreadRouterInput: address(iporProtocol.spreadRouter), - closeSwapServiceUsdtInput: deployerContracts.ammCloseSwapServiceUsdt, - closeSwapServiceUsdcInput: deployerContracts.ammCloseSwapServiceUsdc, - closeSwapServiceDaiInput: deployerContracts.ammCloseSwapServiceDai, - closeSwapServiceStEthInput: _fakeContract + iporOracle_: address(iporProtocol.iporOracle), + messageSigner_: messageSignerAddress, + spreadRouter_: address(iporProtocol.spreadRouter) }) ); @@ -1107,42 +1041,21 @@ contract IporProtocolFactory is Test { ); deployerContracts.ammGovernanceService = address( - new AmmGovernanceService({ - usdtPoolCfg: _preparePoolCfgForGovernanceService( - address(iporProtocol.asset), - address(iporProtocol.ammTreasury), - address(iporProtocol.ammStorage), - address(iporProtocol.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ), - usdcPoolCfg: _prepareFakePoolCfgForGovernanceService(), - daiPoolCfg: _prepareFakePoolCfgForGovernanceService(), - stEthPoolCfg: _prepareFakePoolCfgForGovernanceService(), - weEthPoolCfg: _prepareFakePoolCfgForGovernanceService(), - usdmPoolCfg: _prepareFakePoolCfgForGovernanceService() - }) + new AmmGovernanceServiceBaseV1() ); deployerContracts.powerTokenLens = address(_powerTokenLensBuilder.build()); deployerContracts.liquidityMiningLens = address(_liquidityMiningLensBuilder.build()); deployerContracts.flowService = address(_powerTokenFlowsServiceBuilder.build()); deployerContracts.stakeService = address(_powerTokenStakeServiceBuilder.build()); - - deployerContracts.ammPoolsServiceStEth = _fakeContract; - deployerContracts.ammPoolsLensStEth = _fakeContract; - deployerContracts.ammOpenSwapServiceStEth = _fakeContract; - deployerContracts.ammCloseSwapServiceStEth = _fakeContract; - deployerContracts.ammPoolsServiceWeEth = _fakeContract; - deployerContracts.ammPoolsLensWeEth = _fakeContract; - deployerContracts.ammPoolsLensUsdm = _fakeContract; - deployerContracts.ammPoolsServiceUsdm = _fakeContract; - + deployerContracts.stEth = _fakeAsset; + deployerContracts.weEth = _fakeAsset; + deployerContracts.usdm = _fakeAsset; vm.startPrank(address(_owner)); - IporProtocolRouter(iporProtocol.router).upgradeTo(address(new IporProtocolRouter(deployerContracts))); + IporProtocolRouterEthereum(iporProtocol.router).upgradeTo( + address(new IporProtocolRouterEthereum(deployerContracts)) + ); vm.stopPrank(); iporProtocol.ammSwapsLens = IAmmSwapsLens(address(iporProtocol.router)); @@ -1159,18 +1072,25 @@ contract IporProtocolFactory is Test { iporProtocol.flowService = IPowerTokenFlowsService(address(iporProtocol.router)); iporProtocol.stakeService = IPowerTokenStakeService(address(iporProtocol.router)); - return IporProtocolRouter(iporProtocol.router); + _setupGovernanceServiceForSingleProtocol( + iporProtocol, + cfg, + messageSignerAddress, + deployerContracts.ammCloseSwapServiceUsdt + ); + + return IporProtocolRouterEthereum(iporProtocol.router); } function _getUsdcIporProtocolRouterInstance( BuilderUtils.IporProtocol memory iporProtocol, IporProtocolConfig memory cfg - ) public returns (IporProtocolRouter) { + ) public returns (IporProtocolRouterEthereum) { if (address(iporProtocol.router) == address(0)) { iporProtocol.router = _iporProtocolRouterBuilder.buildEmptyProxy(); } - IporProtocolRouter.DeployedContracts memory deployerContracts; + IporProtocolRouterEthereum.DeployedContracts memory deployerContracts; deployerContracts.ammSwapsLens = address( new AmmSwapsLens( @@ -1233,6 +1153,8 @@ contract IporProtocolFactory is Test { ) ); + deployerContracts.ammPoolsLensBaseV1 = deployerContracts.ammPoolsLens; + deployerContracts.assetManagementLens = address( new AssetManagementLens( IAssetManagementLens.AssetManagementConfiguration({ @@ -1292,17 +1214,9 @@ contract IporProtocolFactory is Test { deployerContracts.ammCloseSwapLens = address( new AmmCloseSwapLens({ - usdtInput: _fakeAsset, - usdcInput: address(iporProtocol.asset), - daiInput: _fakeAsset, - stETHInput: _fakeAsset, - iporOracleInput: address(iporProtocol.iporOracle), - messageSignerInput: messageSignerAddress, - spreadRouterInput: address(iporProtocol.spreadRouter), - closeSwapServiceUsdtInput: deployerContracts.ammCloseSwapServiceUsdt, - closeSwapServiceUsdcInput: deployerContracts.ammCloseSwapServiceUsdc, - closeSwapServiceDaiInput: deployerContracts.ammCloseSwapServiceDai, - closeSwapServiceStEthInput: _fakeContract + iporOracle_: address(iporProtocol.iporOracle), + messageSigner_: messageSignerAddress, + spreadRouter_: address(iporProtocol.spreadRouter) }) ); @@ -1323,23 +1237,7 @@ contract IporProtocolFactory is Test { ); deployerContracts.ammGovernanceService = address( - new AmmGovernanceService({ - usdtPoolCfg: _prepareFakePoolCfgForGovernanceService(), - usdcPoolCfg: _preparePoolCfgForGovernanceService( - address(iporProtocol.asset), - address(iporProtocol.ammTreasury), - address(iporProtocol.ammStorage), - address(iporProtocol.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ), - daiPoolCfg: _prepareFakePoolCfgForGovernanceService(), - stEthPoolCfg: _prepareFakePoolCfgForGovernanceService(), - weEthPoolCfg: _prepareFakePoolCfgForGovernanceService(), - usdmPoolCfg: _prepareFakePoolCfgForGovernanceService() - }) + new AmmGovernanceServiceBaseV1() ); deployerContracts.powerTokenLens = address(_powerTokenLensBuilder.build()); @@ -1347,17 +1245,14 @@ contract IporProtocolFactory is Test { deployerContracts.flowService = address(_powerTokenFlowsServiceBuilder.build()); deployerContracts.stakeService = address(_powerTokenStakeServiceBuilder.build()); - deployerContracts.ammPoolsLensStEth = _fakeContract; - deployerContracts.ammPoolsServiceStEth = _fakeContract; - deployerContracts.ammOpenSwapServiceStEth = _fakeContract; - deployerContracts.ammCloseSwapServiceStEth = _fakeContract; - deployerContracts.ammPoolsLensWeEth = _fakeContract; - deployerContracts.ammPoolsServiceWeEth = _fakeContract; - deployerContracts.ammPoolsLensUsdm = _fakeContract; - deployerContracts.ammPoolsServiceUsdm = _fakeContract; + deployerContracts.stEth = _fakeAsset; + deployerContracts.weEth = _fakeAsset; + deployerContracts.usdm = _fakeAsset; vm.startPrank(address(_owner)); - IporProtocolRouter(iporProtocol.router).upgradeTo(address(new IporProtocolRouter(deployerContracts))); + IporProtocolRouterEthereum(iporProtocol.router).upgradeTo( + address(new IporProtocolRouterEthereum(deployerContracts)) + ); vm.stopPrank(); iporProtocol.ammSwapsLens = IAmmSwapsLens(address(iporProtocol.router)); @@ -1374,25 +1269,25 @@ contract IporProtocolFactory is Test { iporProtocol.flowService = IPowerTokenFlowsService(address(iporProtocol.router)); iporProtocol.stakeService = IPowerTokenStakeService(address(iporProtocol.router)); - return IporProtocolRouter(iporProtocol.router); + _setupGovernanceServiceForSingleProtocol( + iporProtocol, + cfg, + messageSignerAddress, + deployerContracts.ammCloseSwapServiceUsdc + ); + + return IporProtocolRouterEthereum(iporProtocol.router); } function _getDaiIporProtocolRouterInstance( BuilderUtils.IporProtocol memory iporProtocol, IporProtocolConfig memory cfg - ) public returns (IporProtocolRouter) { + ) public returns (IporProtocolRouterEthereum) { if (address(iporProtocol.router) == address(0)) { iporProtocol.router = _iporProtocolRouterBuilder.buildEmptyProxy(); } - IporProtocolRouter.DeployedContracts memory deployerContracts; - - deployerContracts.ammPoolsLensStEth = address(123); - deployerContracts.ammPoolsServiceStEth = address(123); - deployerContracts.ammPoolsLensWeEth = address(123); - deployerContracts.ammPoolsServiceWeEth = address(123); - deployerContracts.ammPoolsLensUsdm = _fakeContract; - deployerContracts.ammPoolsServiceUsdm = _fakeContract; + IporProtocolRouterEthereum.DeployedContracts memory deployerContracts; deployerContracts.ammSwapsLens = address( new AmmSwapsLens( @@ -1454,6 +1349,11 @@ contract IporProtocolFactory is Test { address(iporProtocol.iporOracle) ) ); + + deployerContracts.ammPoolsLensBaseV1 = address( + new AmmPoolsLensBaseV1({iporOracle_: address(iporProtocol.iporOracle)}) + ); + deployerContracts.assetManagementLens = address( new AssetManagementLens( IAssetManagementLens.AssetManagementConfiguration({ @@ -1512,17 +1412,9 @@ contract IporProtocolFactory is Test { deployerContracts.ammCloseSwapLens = address( new AmmCloseSwapLens({ - usdtInput: _fakeAsset, - usdcInput: _fakeAsset, - daiInput: address(iporProtocol.asset), - stETHInput: _fakeAsset, - iporOracleInput: address(iporProtocol.iporOracle), - messageSignerInput: messageSignerAddress, - spreadRouterInput: address(iporProtocol.spreadRouter), - closeSwapServiceUsdtInput: deployerContracts.ammCloseSwapServiceUsdt, - closeSwapServiceUsdcInput: deployerContracts.ammCloseSwapServiceUsdc, - closeSwapServiceDaiInput: deployerContracts.ammCloseSwapServiceDai, - closeSwapServiceStEthInput: _fakeContract + iporOracle_: address(iporProtocol.iporOracle), + messageSigner_: messageSignerAddress, + spreadRouter_: address(iporProtocol.spreadRouter) }) ); @@ -1542,38 +1434,21 @@ contract IporProtocolFactory is Test { }) ); - deployerContracts.ammGovernanceService = address( - new AmmGovernanceService({ - usdtPoolCfg: _prepareFakePoolCfgForGovernanceService(), - usdcPoolCfg: _prepareFakePoolCfgForGovernanceService(), - daiPoolCfg: _preparePoolCfgForGovernanceService( - address(iporProtocol.asset), - address(iporProtocol.ammTreasury), - address(iporProtocol.ammStorage), - address(iporProtocol.assetManagement), - cfg.ammPoolsTreasury, - cfg.ammPoolsTreasuryManager, - cfg.ammCharlieTreasury, - cfg.ammCharlieTreasuryManager - ), - stEthPoolCfg: _prepareFakePoolCfgForGovernanceService(), - weEthPoolCfg: _prepareFakePoolCfgForGovernanceService(), - usdmPoolCfg: _prepareFakePoolCfgForGovernanceService() - }) - ); + deployerContracts.ammGovernanceService = address(new AmmGovernanceServiceBaseV1()); deployerContracts.powerTokenLens = address(_powerTokenLensBuilder.build()); deployerContracts.liquidityMiningLens = address(_liquidityMiningLensBuilder.build()); deployerContracts.flowService = address(_powerTokenFlowsServiceBuilder.build()); deployerContracts.stakeService = address(_powerTokenStakeServiceBuilder.build()); - deployerContracts.ammPoolsLensStEth = address(_fakeContract); - deployerContracts.ammPoolsServiceStEth = address(_fakeContract); - deployerContracts.ammOpenSwapServiceStEth = address(_fakeContract); - deployerContracts.ammCloseSwapServiceStEth = address(_fakeContract); + deployerContracts.stEth = _fakeAsset; + deployerContracts.weEth = _fakeAsset; + deployerContracts.usdm = _fakeAsset; vm.startPrank(address(_owner)); - IporProtocolRouter(iporProtocol.router).upgradeTo(address(new IporProtocolRouter(deployerContracts))); + IporProtocolRouterEthereum(iporProtocol.router).upgradeTo( + address(new IporProtocolRouterEthereum(deployerContracts)) + ); vm.stopPrank(); iporProtocol.ammSwapsLens = IAmmSwapsLens(address(iporProtocol.router)); @@ -1590,12 +1465,19 @@ contract IporProtocolFactory is Test { iporProtocol.flowService = IPowerTokenFlowsService(address(iporProtocol.router)); iporProtocol.stakeService = IPowerTokenStakeService(address(iporProtocol.router)); - return IporProtocolRouter(iporProtocol.router); + _setupGovernanceServiceForSingleProtocol( + iporProtocol, + cfg, + messageSignerAddress, + deployerContracts.ammCloseSwapServiceDai + ); + + return IporProtocolRouterEthereum(iporProtocol.router); } function _prepareFakePoolCfgForGovernanceService() - internal - returns (IAmmGovernanceLens.AmmGovernancePoolConfiguration memory poolCfg) + internal + returns (IAmmGovernanceLens.AmmGovernancePoolConfiguration memory poolCfg) { poolCfg = IAmmGovernanceLens.AmmGovernancePoolConfiguration({ asset: address(_fakeAsset), @@ -1611,8 +1493,8 @@ contract IporProtocolFactory is Test { } function _prepareFakePoolCfgForPoolsService() - internal - returns (AmmPoolsService.AmmPoolsServicePoolConfiguration memory poolCfg) + internal + returns (AmmPoolsService.AmmPoolsServicePoolConfiguration memory poolCfg) { poolCfg = IAmmPoolsService.AmmPoolsServicePoolConfiguration({ asset: address(_fakeAsset), @@ -1627,8 +1509,8 @@ contract IporProtocolFactory is Test { } function _prepareFakePoolCfgForCloseSwapService() - internal - returns (IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg) + internal + returns (IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg) { poolCfg = IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration({ asset: address(_fakeAsset), @@ -1654,8 +1536,8 @@ contract IporProtocolFactory is Test { } function _prepareFakePoolCfgForOpenSwapService() - internal - returns (IAmmOpenSwapLens.AmmOpenSwapServicePoolConfiguration memory poolCfg) + internal + returns (IAmmOpenSwapLens.AmmOpenSwapServicePoolConfiguration memory poolCfg) { poolCfg = IAmmOpenSwapLens.AmmOpenSwapServicePoolConfiguration({ asset: address(_fakeAsset), @@ -1865,6 +1747,185 @@ contract IporProtocolFactory is Test { } } + function _setupGovernanceServiceForSingleProtocol( + BuilderUtils.IporProtocol memory iporProtocol, + IporProtocolConfig memory cfg, + address messageSignerAddress, + address ammCloseSwapServiceAddress + ) internal { + vm.startPrank(address(_owner)); + + // Setup message signer + IAmmGovernanceServiceBaseV1(address(iporProtocol.router)).setMessageSigner(messageSignerAddress); + + // Setup pool configuration + IAmmGovernanceServiceBaseV1(address(iporProtocol.router)).setAmmGovernancePoolConfiguration( + address(iporProtocol.asset), + StorageLibBaseV1.AssetGovernancePoolConfigValue({ + decimals: uint8(iporProtocol.asset.decimals()), + ammStorage: address(iporProtocol.ammStorage), + ammTreasury: address(iporProtocol.ammTreasury), + ammVault: address(iporProtocol.assetManagement), + ammPoolsTreasury: cfg.ammPoolsTreasury, + ammPoolsTreasuryManager: cfg.ammPoolsTreasuryManager, + ammCharlieTreasury: cfg.ammCharlieTreasury, + ammCharlieTreasuryManager: cfg.ammCharlieTreasuryManager + }) + ); + + // Setup AssetLensData + IAmmGovernanceServiceBaseV1(address(iporProtocol.router)).setAssetLensData( + address(iporProtocol.asset), + StorageLibBaseV1.AssetLensDataValue({ + decimals: uint8(iporProtocol.asset.decimals()), + ipToken: address(iporProtocol.ipToken), + ammStorage: address(iporProtocol.ammStorage), + ammTreasury: address(iporProtocol.ammTreasury), + ammVault: address(iporProtocol.assetManagement), + spread: address(iporProtocol.spreadRouter) + }) + ); + + // Setup AssetServices + IAmmGovernanceServiceBaseV1(address(iporProtocol.router)).setAssetServices( + address(iporProtocol.asset), + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: address(iporProtocol.ammPoolsService), + ammOpenSwapService: address(iporProtocol.ammOpenSwapService), + ammCloseSwapService: ammCloseSwapServiceAddress + }) + ); + + vm.stopPrank(); + } + + function _setupGovernanceServiceAfterRouterUpgrade( + Amm memory amm, + AmmConfig memory cfg, + address messageSignerAddress + ) internal { + vm.startPrank(address(_owner)); + + // Setup message signer + IAmmGovernanceServiceBaseV1(address(amm.router)).setMessageSigner(messageSignerAddress); + + // Setup USDT pool configuration + IAmmGovernanceServiceBaseV1(address(amm.router)).setAmmGovernancePoolConfiguration( + address(amm.usdt.asset), + StorageLibBaseV1.AssetGovernancePoolConfigValue({ + decimals: uint8(amm.usdt.asset.decimals()), + ammStorage: address(amm.usdt.ammStorage), + ammTreasury: address(amm.usdt.ammTreasury), + ammVault: address(amm.usdt.assetManagement), + ammPoolsTreasury: cfg.ammPoolsTreasury, + ammPoolsTreasuryManager: cfg.ammPoolsTreasuryManager, + ammCharlieTreasury: cfg.ammCharlieTreasury, + ammCharlieTreasuryManager: cfg.ammCharlieTreasuryManager + }) + ); + + // Setup USDC pool configuration + IAmmGovernanceServiceBaseV1(address(amm.router)).setAmmGovernancePoolConfiguration( + address(amm.usdc.asset), + StorageLibBaseV1.AssetGovernancePoolConfigValue({ + decimals: uint8(amm.usdc.asset.decimals()), + ammStorage: address(amm.usdc.ammStorage), + ammTreasury: address(amm.usdc.ammTreasury), + ammVault: address(amm.usdc.assetManagement), + ammPoolsTreasury: cfg.ammPoolsTreasury, + ammPoolsTreasuryManager: cfg.ammPoolsTreasuryManager, + ammCharlieTreasury: cfg.ammCharlieTreasury, + ammCharlieTreasuryManager: cfg.ammCharlieTreasuryManager + }) + ); + + // Setup DAI pool configuration + IAmmGovernanceServiceBaseV1(address(amm.router)).setAmmGovernancePoolConfiguration( + address(amm.dai.asset), + StorageLibBaseV1.AssetGovernancePoolConfigValue({ + decimals: uint8(amm.dai.asset.decimals()), + ammStorage: address(amm.dai.ammStorage), + ammTreasury: address(amm.dai.ammTreasury), + ammVault: address(amm.dai.assetManagement), + ammPoolsTreasury: cfg.ammPoolsTreasury, + ammPoolsTreasuryManager: cfg.ammPoolsTreasuryManager, + ammCharlieTreasury: cfg.ammCharlieTreasury, + ammCharlieTreasuryManager: cfg.ammCharlieTreasuryManager + }) + ); + + // Setup AssetLensData for USDT + IAmmGovernanceServiceBaseV1(address(amm.router)).setAssetLensData( + address(amm.usdt.asset), + StorageLibBaseV1.AssetLensDataValue({ + decimals: uint8(amm.usdt.asset.decimals()), + ipToken: address(amm.usdt.ipToken), + ammStorage: address(amm.usdt.ammStorage), + ammTreasury: address(amm.usdt.ammTreasury), + ammVault: address(amm.usdt.assetManagement), + spread: address(amm.spreadRouter) + }) + ); + + // Setup AssetLensData for USDC + IAmmGovernanceServiceBaseV1(address(amm.router)).setAssetLensData( + address(amm.usdc.asset), + StorageLibBaseV1.AssetLensDataValue({ + decimals: uint8(amm.usdc.asset.decimals()), + ipToken: address(amm.usdc.ipToken), + ammStorage: address(amm.usdc.ammStorage), + ammTreasury: address(amm.usdc.ammTreasury), + ammVault: address(amm.usdc.assetManagement), + spread: address(amm.spreadRouter) + }) + ); + + // Setup AssetLensData for DAI + IAmmGovernanceServiceBaseV1(address(amm.router)).setAssetLensData( + address(amm.dai.asset), + StorageLibBaseV1.AssetLensDataValue({ + decimals: uint8(amm.dai.asset.decimals()), + ipToken: address(amm.dai.ipToken), + ammStorage: address(amm.dai.ammStorage), + ammTreasury: address(amm.dai.ammTreasury), + ammVault: address(amm.dai.assetManagement), + spread: address(amm.spreadRouter) + }) + ); + + // Setup AssetServices for USDT + IAmmGovernanceServiceBaseV1(address(amm.router)).setAssetServices( + address(amm.usdt.asset), + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: address(amm.usdt.ammPoolsService), + ammOpenSwapService: address(amm.usdt.ammOpenSwapService), + ammCloseSwapService: address(amm.usdt.ammCloseSwapServiceUsdt) + }) + ); + + // Setup AssetServices for USDC + IAmmGovernanceServiceBaseV1(address(amm.router)).setAssetServices( + address(amm.usdc.asset), + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: address(amm.usdc.ammPoolsService), + ammOpenSwapService: address(amm.usdc.ammOpenSwapService), + ammCloseSwapService: address(amm.usdc.ammCloseSwapServiceUsdc) + }) + ); + + // Setup AssetServices for DAI + IAmmGovernanceServiceBaseV1(address(amm.router)).setAssetServices( + address(amm.dai.asset), + StorageLibBaseV1.AssetServicesValue({ + ammPoolsService: address(amm.dai.ammPoolsService), + ammOpenSwapService: address(amm.dai.ammOpenSwapService), + ammCloseSwapService: address(amm.dai.ammCloseSwapServiceDai) + }) + ); + + vm.stopPrank(); + } + function setupUsers( IporProtocolFactory.IporProtocolConfig memory cfg, BuilderUtils.IporProtocol memory iporProtocol From 408f93e906e27d802bfa8cf839d48e43f92e4120 Mon Sep 17 00:00:00 2001 From: Mario <85162486+mario-ipor@users.noreply.github.com> Date: Fri, 14 Nov 2025 08:23:00 +0100 Subject: [PATCH 6/6] CR fix. Spread appropriate for pool. (#762) * CR fix. Spread appropriate for pool. * CR Fix. --- .../amm/libraries/types/AmmInternalTypes.sol | 2 +- .../ethereum/amm-commons/AmmCloseSwapLens.sol | 161 ++++++++++++++++-- contracts/interfaces/ILiquidityMiningLens.sol | 2 +- test/utils/factory/IporProtocolFactory.sol | 32 ++-- 4 files changed, 167 insertions(+), 30 deletions(-) diff --git a/contracts/amm/libraries/types/AmmInternalTypes.sol b/contracts/amm/libraries/types/AmmInternalTypes.sol index 884f537e5..f53ed1350 100644 --- a/contracts/amm/libraries/types/AmmInternalTypes.sol +++ b/contracts/amm/libraries/types/AmmInternalTypes.sol @@ -68,7 +68,7 @@ library AmmInternalTypes { struct OpenSwapItem { /// @notice Swap ID uint32 swapId; - /// @notcie Next swap ID in linked list + /// @notice Next swap ID in linked list uint32 nextSwapId; /// @notice Previous swap ID in linked list uint32 previousSwapId; diff --git a/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol b/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol index 89cafcbec..89c0075ec 100644 --- a/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol +++ b/contracts/chains/ethereum/amm-commons/AmmCloseSwapLens.sol @@ -1,48 +1,60 @@ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity 0.8.26; +import "@openzeppelin/contracts/utils/Address.sol"; + import "../../../interfaces/types/IporTypes.sol"; import "../../../interfaces/types/AmmTypes.sol"; import "../../../interfaces/IIporOracle.sol"; import "../../../interfaces/IAmmCloseSwapLens.sol"; import "../../../interfaces/IAmmCloseSwapService.sol"; -import "../../../interfaces/IAmmStorage.sol"; import "../../../libraries/errors/IporErrors.sol"; import "../../../libraries/IporContractValidator.sol"; import "../../../libraries/AmmCloseSwapServicePoolConfigurationLib.sol"; -import "../../../base/amm/libraries/SwapLogicBaseV1.sol"; -import "../../../base/amm/libraries/SwapCloseLogicLibBaseV1.sol"; import "../../../amm/libraries/SwapCloseLogicLib.sol"; import "../../../base/types/AmmTypesBaseV1.sol"; -import {StorageLibBaseV1} from "../../../base/libraries/StorageLibBaseV1.sol"; +import "../../../base/amm/libraries/SwapLogicBaseV1.sol"; +import "../../../base/amm/libraries/SwapCloseLogicLibBaseV1.sol"; +import "../../../base/amm/services/AmmCloseSwapServiceBaseV1.sol"; -/// @dev Legacy AmmCloseSwapLens for DAI/USDT/USDC which uses legacy SwapCloseLogicLib (not BaseV1) /// @dev It is not recommended to use service contract directly, should be used only through IporProtocolRouter. contract AmmCloseSwapLens is IAmmCloseSwapLens { + using Address for address; using IporContractValidator for address; + using SwapLogicBaseV1 for AmmTypesBaseV1.Swap; using AmmCloseSwapServicePoolConfigurationLib for IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration; + address public immutable usdt; + address public immutable usdc; + address public immutable dai; + address public immutable stETH; address public immutable iporOracle; - address public immutable messageSigner; - address public immutable spreadRouter; - constructor(address iporOracle_, address messageSigner_, address spreadRouter_) { + constructor( + address usdt_, + address usdc_, + address dai_, + address stETH_, + address iporOracle_ + ) { + usdt = usdt_.checkAddress(); + usdc = usdc_.checkAddress(); + dai = dai_.checkAddress(); + stETH = stETH_.checkAddress(); iporOracle = iporOracle_.checkAddress(); - messageSigner = messageSigner_.checkAddress(); - spreadRouter = spreadRouter_.checkAddress(); } function getAmmCloseSwapServicePoolConfiguration( - address asset + address asset_ ) external view override returns (AmmCloseSwapServicePoolConfiguration memory) { StorageLibBaseV1.AssetServicesValue memory servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ - asset + asset_ ]; if (servicesCfg.ammCloseSwapService != address(0)) { return IAmmCloseSwapService(servicesCfg.ammCloseSwapService).getPoolConfiguration(); } else { - revert IporErrors.UnsupportedAsset(IporErrors.ASSET_NOT_SUPPORTED, asset); + revert IporErrors.UnsupportedAsset(IporErrors.ASSET_NOT_SUPPORTED, asset_); } } @@ -54,6 +66,36 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { uint256 closeTimestamp, AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput ) external view override returns (AmmTypes.ClosingSwapDetails memory closingSwapDetails) { + if (asset == usdt || asset == usdc || asset == dai) { + closingSwapDetails = _getClosingSwapDetailsForStable( + asset, + account, + direction, + swapId, + closeTimestamp, + riskIndicatorsInput + ); + } else if (asset == stETH) { + closingSwapDetails = _getClosingSwapDetailsForStEth( + account, + direction, + swapId, + closeTimestamp, + riskIndicatorsInput + ); + } else { + revert IporErrors.UnsupportedAsset(IporErrors.ASSET_NOT_SUPPORTED, asset); + } + } + + function _getClosingSwapDetailsForStable( + address asset, + address account, + AmmTypes.SwapDirection direction, + uint256 swapId, + uint256 closeTimestamp, + AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput + ) internal view returns (AmmTypes.ClosingSwapDetails memory closingSwapDetails) { StorageLibBaseV1.AssetServicesValue memory servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ asset ]; @@ -76,6 +118,7 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { require(swap.id > 0, AmmErrors.INCORRECT_SWAP_ID); int256 swapPnlValueToDate; + if (direction == AmmTypes.SwapDirection.PAY_FIXED_RECEIVE_FLOATING) { swapPnlValueToDate = SwapLogicBaseV1.calculatePnlPayFixed( swap.openTimestamp, @@ -86,7 +129,7 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { block.timestamp, accruedIpor.ibtPrice ); - } else { + } else if (direction == AmmTypes.SwapDirection.PAY_FLOATING_RECEIVE_FIXED) { swapPnlValueToDate = SwapLogicBaseV1.calculatePnlReceiveFixed( swap.openTimestamp, swap.collateral, @@ -96,6 +139,8 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { block.timestamp, accruedIpor.ibtPrice ); + } else { + revert(AmmErrors.UNSUPPORTED_DIRECTION); } (closingSwapDetails.closableStatus, closingSwapDetails.swapUnwindRequired) = SwapCloseLogicLibBaseV1 @@ -133,8 +178,8 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { closingSwapDetails.pnlValue ) = SwapCloseLogicLib.calculateSwapUnwindWhenUnwindRequired( AmmTypes.UnwindParams({ - messageSigner: messageSigner, - spreadRouter: spreadRouter, + messageSigner: StorageLibBaseV1.getMessageSignerStorage().value, + spreadRouter: poolCfg.spread, ammStorage: poolCfg.ammStorage, ammTreasury: poolCfg.ammTreasury, direction: direction, @@ -150,4 +195,88 @@ contract AmmCloseSwapLens is IAmmCloseSwapLens { closingSwapDetails.pnlValue = swapPnlValueToDate; } } + + function _getClosingSwapDetailsForStEth( + address account, + AmmTypes.SwapDirection direction, + uint256 swapId, + uint256 closeTimestamp, + AmmTypes.CloseSwapRiskIndicatorsInput calldata riskIndicatorsInput + ) internal view returns (AmmTypes.ClosingSwapDetails memory closingSwapDetails) { + StorageLibBaseV1.AssetServicesValue memory servicesCfg = StorageLibBaseV1.getAssetServicesStorage().value[ + stETH + ]; + + if (servicesCfg.ammCloseSwapService == address(0)) { + revert IporErrors.UnsupportedAsset(IporErrors.ASSET_NOT_SUPPORTED, stETH); + } + + IAmmCloseSwapLens.AmmCloseSwapServicePoolConfiguration memory poolCfg = IAmmCloseSwapService( + servicesCfg.ammCloseSwapService + ).getPoolConfiguration(); + + IporTypes.AccruedIpor memory accruedIpor = IIporOracle(iporOracle).getAccruedIndex( + block.timestamp, + poolCfg.asset + ); + + AmmTypesBaseV1.Swap memory swap = IAmmStorageBaseV1(poolCfg.ammStorage).getSwap(direction, swapId); + + require(swap.id > 0, AmmErrors.INCORRECT_SWAP_ID); + + int256 swapPnlValueToDate = swap.calculatePnl(block.timestamp, accruedIpor.ibtPrice); + + (closingSwapDetails.closableStatus, closingSwapDetails.swapUnwindRequired) = SwapCloseLogicLibBaseV1 + .getClosableStatusForSwap( + AmmTypesBaseV1.ClosableSwapInput({ + account: account, + asset: poolCfg.asset, + closeTimestamp: closeTimestamp, + swapBuyer: swap.buyer, + swapOpenTimestamp: swap.openTimestamp, + swapCollateral: swap.collateral, + swapTenor: swap.tenor, + swapState: swap.state, + swapPnlValueToDate: swapPnlValueToDate, + minLiquidationThresholdToCloseBeforeMaturityByCommunity: poolCfg + .minLiquidationThresholdToCloseBeforeMaturityByCommunity, + minLiquidationThresholdToCloseBeforeMaturityByBuyer: poolCfg + .minLiquidationThresholdToCloseBeforeMaturityByBuyer, + timeBeforeMaturityAllowedToCloseSwapByCommunity: poolCfg + .timeBeforeMaturityAllowedToCloseSwapByCommunity, + timeBeforeMaturityAllowedToCloseSwapByBuyer: poolCfg.getTimeBeforeMaturityAllowedToCloseSwapByBuyer( + swap.tenor + ), + timeAfterOpenAllowedToCloseSwapWithUnwinding: poolCfg + .getTimeAfterOpenAllowedToCloseSwapWithUnwinding(swap.tenor) + }) + ); + + if (closingSwapDetails.swapUnwindRequired == true) { + ( + closingSwapDetails.swapUnwindPnlValue, + closingSwapDetails.swapUnwindOpeningFeeAmount, + closingSwapDetails.swapUnwindFeeLPAmount, + closingSwapDetails.swapUnwindFeeTreasuryAmount, + closingSwapDetails.pnlValue + ) = SwapCloseLogicLibBaseV1.calculateSwapUnwindWhenUnwindRequired( + AmmTypesBaseV1.UnwindParams({ + asset: poolCfg.asset, + messageSigner: StorageLibBaseV1.getMessageSignerStorage().value, + spread: poolCfg.spread, + ammStorage: poolCfg.ammStorage, + ammTreasury: poolCfg.ammTreasury, + closeTimestamp: closeTimestamp, + swapPnlValueToDate: swapPnlValueToDate, + indexValue: accruedIpor.indexValue, + swap: swap, + unwindingFeeRate: poolCfg.unwindingFeeRate, + unwindingFeeTreasuryPortionRate: poolCfg.unwindingFeeTreasuryPortionRate, + riskIndicatorsInputs: riskIndicatorsInput + }) + ); + } else { + closingSwapDetails.pnlValue = swapPnlValueToDate; + } + } } diff --git a/contracts/interfaces/ILiquidityMiningLens.sol b/contracts/interfaces/ILiquidityMiningLens.sol index 0babe1e21..45c880fb3 100644 --- a/contracts/interfaces/ILiquidityMiningLens.sol +++ b/contracts/interfaces/ILiquidityMiningLens.sol @@ -41,7 +41,7 @@ interface ILiquidityMiningLens { uint128 compositeMultiplierCumulativePrevBlock; /// @notice lpToken account's balance uint128 lpTokenBalance; - /// @notive PowerUp is a result of logarithmic equastion, + /// @notice PowerUp is a result of logarithmic equastion, /// @dev powerUp < 100 *10^18 uint72 powerUp; /// @notice balance of Power Tokens delegated to LiquidityMining diff --git a/test/utils/factory/IporProtocolFactory.sol b/test/utils/factory/IporProtocolFactory.sol index 5b08d6b78..ff85c5fe6 100644 --- a/test/utils/factory/IporProtocolFactory.sol +++ b/test/utils/factory/IporProtocolFactory.sol @@ -784,9 +784,11 @@ contract IporProtocolFactory is Test { deployerContracts.ammCloseSwapLens = address( new AmmCloseSwapLens({ - iporOracle_: address(amm.iporOracle), - messageSigner_: messageSignerAddress, - spreadRouter_: address(amm.spreadRouter) + usdt_: address(amm.usdt.asset), + usdc_: address(amm.usdc.asset), + dai_: address(amm.dai.asset), + stETH_: address(amm.stEth.asset), + iporOracle_: address(amm.iporOracle) }) ); @@ -1018,9 +1020,11 @@ contract IporProtocolFactory is Test { deployerContracts.ammCloseSwapLens = address( new AmmCloseSwapLens({ - iporOracle_: address(iporProtocol.iporOracle), - messageSigner_: messageSignerAddress, - spreadRouter_: address(iporProtocol.spreadRouter) + usdt_: address(iporProtocol.asset), + usdc_: address(_fakeAsset), + dai_: address(_fakeAsset), + stETH_: address(_fakeAsset), + iporOracle_: address(iporProtocol.iporOracle) }) ); @@ -1214,9 +1218,11 @@ contract IporProtocolFactory is Test { deployerContracts.ammCloseSwapLens = address( new AmmCloseSwapLens({ - iporOracle_: address(iporProtocol.iporOracle), - messageSigner_: messageSignerAddress, - spreadRouter_: address(iporProtocol.spreadRouter) + usdt_: address(_fakeAsset), + usdc_: address(iporProtocol.asset), + dai_: address(_fakeAsset), + stETH_: address(_fakeAsset), + iporOracle_: address(iporProtocol.iporOracle) }) ); @@ -1412,9 +1418,11 @@ contract IporProtocolFactory is Test { deployerContracts.ammCloseSwapLens = address( new AmmCloseSwapLens({ - iporOracle_: address(iporProtocol.iporOracle), - messageSigner_: messageSignerAddress, - spreadRouter_: address(iporProtocol.spreadRouter) + usdt_: address(_fakeAsset), + usdc_: address(_fakeAsset), + dai_: address(iporProtocol.asset), + stETH_: address(_fakeAsset), + iporOracle_: address(iporProtocol.iporOracle) }) );