From ad7a5f549cd0ad52e0bef91ec2cf2d3372da1354 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Thu, 17 Oct 2024 16:28:05 +0200 Subject: [PATCH 01/44] feat: add setGlobalSlippage() --- src/interfaces/ISuperformRouterPlus.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/interfaces/ISuperformRouterPlus.sol b/src/interfaces/ISuperformRouterPlus.sol index b5d356c1a..759dcf635 100644 --- a/src/interfaces/ISuperformRouterPlus.sol +++ b/src/interfaces/ISuperformRouterPlus.sol @@ -227,4 +227,9 @@ interface ISuperformRouterPlus is IBaseSuperformRouterPlus { /// @dev Forwards dust to Paymaster /// @param token_ the token to forward function forwardDustToPaymaster(address token_) external; + + /// @dev only callable by Emergency Admin + /// @notice sets the global slippage for all rebalances + /// @param slippage_ The slippage tolerance for same chain rebalances + function setGlobalSlippage(uint256 slippage_) external; } From b78b78e84669603971debbf33320c27fc40a5f31 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Thu, 17 Oct 2024 16:31:38 +0200 Subject: [PATCH 02/44] feat: add _hasRole() --- src/router-plus/SuperformRouterPlus.sol | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index f363d7c8c..241390719 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -18,6 +18,7 @@ import { import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ISuperformRouterPlus, IERC20 } from "src/interfaces/ISuperformRouterPlus.sol"; import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAsync.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; /// @title SuperformRouterPlus /// @dev Performs rebalances and deposits on the Superform platform @@ -25,6 +26,7 @@ import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAs contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { using SafeERC20 for IERC20; + uint256 public GLOBAL_SLIPPAGE; uint256 public ROUTER_PLUS_PAYLOAD_ID; ////////////////////////////////////////////////////////////// @@ -596,4 +598,12 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { } } } + + /// @dev returns if an address has a specific role + /// @param id_ the role id + /// @param addressToCheck_ the address to check + /// @return true if the address has the role, false otherwise + function _hasRole(bytes32 id_, address addressToCheck_) internal view returns (bool) { + return ISuperRBAC(superRegistry.getAddress(keccak256("SUPER_RBAC"))).hasRole(id_, addressToCheck_); + } } From 8ebe70641b45618b2fa57fa9ea7a23595a95725e Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Thu, 17 Oct 2024 16:32:01 +0200 Subject: [PATCH 03/44] feat: add setGlobalSlippage() --- src/router-plus/SuperformRouterPlus.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 241390719..c197f8587 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -391,6 +391,15 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { } } + /// @inheritdoc ISuperformRouterPlus + function setGlobalSlippage(uint256 slippage_) external override { + if (!_hasRole(keccak256("EMERGENCY_ADMIN_ROLE"), msg.sender)) { + revert Error.NOT_PRIVILEGED_CALLER(keccak256("EMERGENCY_ADMIN_ROLE")); + } + + GLOBAL_SLIPPAGE = slippage_; + } + ////////////////////////////////////////////////////////////// // INTERNAL FUNCTIONS // ////////////////////////////////////////////////////////////// From f2c4cebe632e2aa6d9e4ea091a9caf88e3a74f8e Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Fri, 18 Oct 2024 07:35:40 +0200 Subject: [PATCH 04/44] refactor: decode amountIn in rebalanceSinglePosition() --- src/router-plus/SuperformRouterPlus.sol | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index c197f8587..6715a05c5 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -18,7 +18,9 @@ import { import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ISuperformRouterPlus, IERC20 } from "src/interfaces/ISuperformRouterPlus.sol"; import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAsync.sol"; +import { LiqRequest } from "src/types/DataTypes.sol"; import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; +import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; /// @title SuperformRouterPlus /// @dev Performs rebalances and deposits on the Superform platform @@ -47,10 +49,27 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { address superPositions = _getAddress(keccak256("SUPER_POSITIONS")); address router = _getAddress(keccak256("SUPERFORM_ROUTER")); + LiqRequest memory liqReq = abi.decode(_parseCallData(args.rebalanceToCallData), (SingleVaultSFData)).liqRequest; + + uint8 bridgeId_ = liqReq.bridgeId; + + uint256 amountIn = IBridgeValidator(superRegistry.getBridgeValidator(bridgeId_)).decodeAmountIn( + liqReq.txData, false + ); + + address interimAsset = liqReq.token; + (uint256 balanceBefore, uint256 totalFee) = _beforeRebalanceChecks( args.interimAsset, args.receiverAddressSP, args.rebalanceFromMsgValue, args.rebalanceToMsgValue ); + uint256 amountToDeposit = IERC20(args.interimAsset).balanceOf(address(this)) - balanceBefore; + + if ( + GLOBAL_SLIPPAGE * amountIn + < ((amountToDeposit * (GLOBAL_SLIPPAGE - args.slippage))) + ) revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); + /// @dev transfers a single superPosition to this contract and approves router _transferSuperPositions(superPositions, router, args.receiverAddressSP, args.id, args.sharesToRedeem); From 8a23ca222aaf2a3a6fbb83b8edceb542a7fd8621 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Fri, 18 Oct 2024 08:03:20 +0200 Subject: [PATCH 05/44] fix: add slippage check in rebalanceSinglePosition() --- src/router-plus/SuperformRouterPlus.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 6715a05c5..1c997af0c 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -57,8 +57,6 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { liqReq.txData, false ); - address interimAsset = liqReq.token; - (uint256 balanceBefore, uint256 totalFee) = _beforeRebalanceChecks( args.interimAsset, args.receiverAddressSP, args.rebalanceFromMsgValue, args.rebalanceToMsgValue ); From ea9d03e7b916e3befa1d13a4e98c2f24d6bc1b01 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Fri, 18 Oct 2024 18:01:49 +0200 Subject: [PATCH 06/44] fix: update approval amount in _transferSuperPositions() --- src/router-plus/SuperformRouterPlus.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 1c997af0c..aeaf9752c 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -64,12 +64,12 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { uint256 amountToDeposit = IERC20(args.interimAsset).balanceOf(address(this)) - balanceBefore; if ( - GLOBAL_SLIPPAGE * amountIn - < ((amountToDeposit * (GLOBAL_SLIPPAGE - args.slippage))) + GLOBAL_SLIPPAGE * amountToDeposit + < ((amountIn * (GLOBAL_SLIPPAGE - args.slippage))) ) revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); /// @dev transfers a single superPosition to this contract and approves router - _transferSuperPositions(superPositions, router, args.receiverAddressSP, args.id, args.sharesToRedeem); + _transferSuperPositions(superPositions, router, args.receiverAddressSP, args.id, amountIn); uint256[] memory sharesToRedeem = new uint256[](1); From 369bf3e31483a7896598b73feed6259909740a5f Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Sat, 19 Oct 2024 11:01:17 +0200 Subject: [PATCH 07/44] fix: move global slippage check to _rebalancePositionsSync() --- src/router-plus/SuperformRouterPlus.sol | 35 +++++++++++++------------ 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index aeaf9752c..2bc6c50a9 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -49,27 +49,12 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { address superPositions = _getAddress(keccak256("SUPER_POSITIONS")); address router = _getAddress(keccak256("SUPERFORM_ROUTER")); - LiqRequest memory liqReq = abi.decode(_parseCallData(args.rebalanceToCallData), (SingleVaultSFData)).liqRequest; - - uint8 bridgeId_ = liqReq.bridgeId; - - uint256 amountIn = IBridgeValidator(superRegistry.getBridgeValidator(bridgeId_)).decodeAmountIn( - liqReq.txData, false - ); - (uint256 balanceBefore, uint256 totalFee) = _beforeRebalanceChecks( args.interimAsset, args.receiverAddressSP, args.rebalanceFromMsgValue, args.rebalanceToMsgValue ); - uint256 amountToDeposit = IERC20(args.interimAsset).balanceOf(address(this)) - balanceBefore; - - if ( - GLOBAL_SLIPPAGE * amountToDeposit - < ((amountIn * (GLOBAL_SLIPPAGE - args.slippage))) - ) revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); - /// @dev transfers a single superPosition to this contract and approves router - _transferSuperPositions(superPositions, router, args.receiverAddressSP, args.id, amountIn); + _transferSuperPositions(superPositions, router, args.receiverAddressSP, args.id, args.sharesToRedeem); uint256[] memory sharesToRedeem = new uint256[](1); @@ -436,6 +421,8 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert INVALID_REBALANCE_FROM_SELECTOR(); } + LiqRequest memory liqReq; + if (args.action == Actions.REBALANCE_FROM_SINGLE) { SingleDirectSingleVaultStateReq memory req = abi.decode(_parseCallData(callData), (SingleDirectSingleVaultStateReq)); @@ -452,6 +439,9 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { if (req.superformData.receiverAddress != address(this)) { revert REBALANCE_SINGLE_POSITIONS_UNEXPECTED_RECEIVER_ADDRESS(); } + + liqReq = abi.decode(_parseCallData(rebalanceToCallData), (SingleVaultSFData)).liqRequest; + } else { /// then must be Actions.REBALANCE_FROM_MULTI SingleDirectMultiVaultStateReq memory req = @@ -481,6 +471,17 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { if (amountToDeposit == 0) revert Error.ZERO_AMOUNT(); + uint8 bridgeId_ = liqReq.bridgeId; + + uint256 amountIn = IBridgeValidator(superRegistry.getBridgeValidator(bridgeId_)).decodeAmountIn( + liqReq.txData, false + ); + + if ( + GLOBAL_SLIPPAGE * amountToDeposit + < ((amountIn * (GLOBAL_SLIPPAGE - args.slippage))) + ) revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); + if ( ENTIRE_SLIPPAGE * amountToDeposit < ((args.expectedAmountToReceivePostRebalanceFrom * (ENTIRE_SLIPPAGE - args.slippage))) @@ -493,7 +494,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert INVALID_DEPOSIT_SELECTOR(); } - _deposit(router_, interimAsset, amountToDeposit, args.rebalanceToMsgValue, rebalanceToCallData); + _deposit(router_, interimAsset, amountIn, args.rebalanceToMsgValue, rebalanceToCallData); } function _transferSuperPositions( From 9ead37ad9799293c6aa3439eb1d68c933993e900 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:55:25 +0200 Subject: [PATCH 08/44] feat: test setGlobalSlippage() --- .../router-plus/SuperformRouterPlus.t.sol | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 35dcb6a50..d24368249 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -4167,4 +4167,29 @@ contract SuperformRouterPlusTest is ProtocolActions { calldata_ := add(data, 0x04) } } + + function test_setGlobalSlippage() public { + // Test invalid caller + vm.startPrank(address(12345)); + vm.expectRevert(); + SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(100); + vm.stopPrank(); + + // Test slippage greater than ENTIRE_SLIPPAGE + vm.startPrank(deployer); + vm.expectRevert(); + SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(1000000); + vm.stopPrank(); + + // Test slippage 0 + vm.startPrank(deployer); + vm.expectRevert(); + SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(0); + vm.stopPrank(); + + // Test slippage valid + vm.startPrank(deployer); + SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(100); + vm.stopPrank(); + } } From af6b2f57bbb99ef6025325893579fe21dde5e838 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 21 Oct 2024 18:55:53 +0200 Subject: [PATCH 09/44] refactor: add additional slippage checks to _rebalancePositionsSync() --- src/router-plus/SuperformRouterPlus.sol | 59 +++++++++++++++++++------ 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 2bc6c50a9..2ec899398 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -35,7 +35,9 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { } + constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { + GLOBAL_SLIPPAGE = 10; + } ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // @@ -399,6 +401,8 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert Error.NOT_PRIVILEGED_CALLER(keccak256("EMERGENCY_ADMIN_ROLE")); } + require(slippage_ <= ENTIRE_SLIPPAGE && slippage_ > 0, "Invalid slippage"); + GLOBAL_SLIPPAGE = slippage_; } @@ -421,7 +425,8 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert INVALID_REBALANCE_FROM_SELECTOR(); } - LiqRequest memory liqReq; + uint256 amountIn; + bool containsSwapData; if (args.action == Actions.REBALANCE_FROM_SINGLE) { SingleDirectSingleVaultStateReq memory req = @@ -440,14 +445,27 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert REBALANCE_SINGLE_POSITIONS_UNEXPECTED_RECEIVER_ADDRESS(); } - liqReq = abi.decode(_parseCallData(rebalanceToCallData), (SingleVaultSFData)).liqRequest; + LiqRequest memory liqReq = abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData.liqRequest; + bytes memory txData = liqReq.txData; + if (txData.length == 0) { + amountIn = req.superformData.amount; + } else { + uint8 bridgeId_ = liqReq.bridgeId; + + amountIn = IBridgeValidator(superRegistry.getBridgeValidator(bridgeId_)).decodeAmountIn( + liqReq.txData, false + ); + containsSwapData = true; + } } else { /// then must be Actions.REBALANCE_FROM_MULTI SingleDirectMultiVaultStateReq memory req = abi.decode(_parseCallData(callData), (SingleDirectMultiVaultStateReq)); uint256 len = req.superformData.liqRequests.length; + LiqRequest[] memory liqReqs = abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectMultiVaultStateReq)).superformData.liqRequests; + for (uint256 i; i < len; ++i) { // Validate that the token and chainId is equal in all indexes if (req.superformData.liqRequests[i].token != args.interimAsset) { @@ -462,6 +480,23 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { if (req.superformData.receiverAddress != address(this)) { revert REBALANCE_MULTI_POSITIONS_UNEXPECTED_RECEIVER_ADDRESS(); } + + bytes memory txData = liqReqs[i].txData; // if length = 1; amount = sum(amounts) | else amounts must match the amounts being sent + if (txData.length == 0) { + amountIn += req.superformData.amounts[i]; + } else if (txData.length == 1 && req.superformData.amounts.length > 1) { // ToDo: check if this is correct + for (uint256 j; j < req.superformData.amounts.length; ++j) { + amountIn += req.superformData.amounts[j]; + } + containsSwapData = true; + } else { + uint8 bridgeId_ = liqReqs[i].bridgeId; + + amountIn += IBridgeValidator(superRegistry.getBridgeValidator(bridgeId_)).decodeAmountIn( + liqReqs[i].txData, false + ); + containsSwapData = true; + } } } /// @dev send SPs to router @@ -471,17 +506,6 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { if (amountToDeposit == 0) revert Error.ZERO_AMOUNT(); - uint8 bridgeId_ = liqReq.bridgeId; - - uint256 amountIn = IBridgeValidator(superRegistry.getBridgeValidator(bridgeId_)).decodeAmountIn( - liqReq.txData, false - ); - - if ( - GLOBAL_SLIPPAGE * amountToDeposit - < ((amountIn * (GLOBAL_SLIPPAGE - args.slippage))) - ) revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); - if ( ENTIRE_SLIPPAGE * amountToDeposit < ((args.expectedAmountToReceivePostRebalanceFrom * (ENTIRE_SLIPPAGE - args.slippage))) @@ -489,6 +513,13 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert Error.VAULT_IMPLEMENTATION_FAILED(); } + if (containsSwapData) { + if ( + ENTIRE_SLIPPAGE * amountToDeposit + < ((amountIn * (ENTIRE_SLIPPAGE - GLOBAL_SLIPPAGE))) + ) revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); + } + /// @dev step 3: rebalance into a new superform with rebalanceCallData if (!whitelistedSelectors[Actions.DEPOSIT][_parseSelectorMem(rebalanceToCallData)]) { revert INVALID_DEPOSIT_SELECTOR(); From b912b3cc6f30e6420c31a3ada9b48d83f7ca591d Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Mon, 21 Oct 2024 20:09:30 +0100 Subject: [PATCH 10/44] test: fix amount in calculation --- src/router-plus/SuperformRouterPlus.sol | 123 +++++++++++++++--------- 1 file changed, 78 insertions(+), 45 deletions(-) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 2ec899398..1f9217347 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -35,7 +35,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { + constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { GLOBAL_SLIPPAGE = 10; } @@ -425,9 +425,6 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert INVALID_REBALANCE_FROM_SELECTOR(); } - uint256 amountIn; - bool containsSwapData; - if (args.action == Actions.REBALANCE_FROM_SINGLE) { SingleDirectSingleVaultStateReq memory req = abi.decode(_parseCallData(callData), (SingleDirectSingleVaultStateReq)); @@ -444,28 +441,12 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { if (req.superformData.receiverAddress != address(this)) { revert REBALANCE_SINGLE_POSITIONS_UNEXPECTED_RECEIVER_ADDRESS(); } - - LiqRequest memory liqReq = abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData.liqRequest; - - bytes memory txData = liqReq.txData; - if (txData.length == 0) { - amountIn = req.superformData.amount; - } else { - uint8 bridgeId_ = liqReq.bridgeId; - - amountIn = IBridgeValidator(superRegistry.getBridgeValidator(bridgeId_)).decodeAmountIn( - liqReq.txData, false - ); - containsSwapData = true; - } } else { /// then must be Actions.REBALANCE_FROM_MULTI SingleDirectMultiVaultStateReq memory req = abi.decode(_parseCallData(callData), (SingleDirectMultiVaultStateReq)); uint256 len = req.superformData.liqRequests.length; - LiqRequest[] memory liqReqs = abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectMultiVaultStateReq)).superformData.liqRequests; - for (uint256 i; i < len; ++i) { // Validate that the token and chainId is equal in all indexes if (req.superformData.liqRequests[i].token != args.interimAsset) { @@ -480,23 +461,6 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { if (req.superformData.receiverAddress != address(this)) { revert REBALANCE_MULTI_POSITIONS_UNEXPECTED_RECEIVER_ADDRESS(); } - - bytes memory txData = liqReqs[i].txData; // if length = 1; amount = sum(amounts) | else amounts must match the amounts being sent - if (txData.length == 0) { - amountIn += req.superformData.amounts[i]; - } else if (txData.length == 1 && req.superformData.amounts.length > 1) { // ToDo: check if this is correct - for (uint256 j; j < req.superformData.amounts.length; ++j) { - amountIn += req.superformData.amounts[j]; - } - containsSwapData = true; - } else { - uint8 bridgeId_ = liqReqs[i].bridgeId; - - amountIn += IBridgeValidator(superRegistry.getBridgeValidator(bridgeId_)).decodeAmountIn( - liqReqs[i].txData, false - ); - containsSwapData = true; - } } } /// @dev send SPs to router @@ -513,21 +477,90 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert Error.VAULT_IMPLEMENTATION_FAILED(); } - if (containsSwapData) { - if ( - ENTIRE_SLIPPAGE * amountToDeposit - < ((amountIn * (ENTIRE_SLIPPAGE - GLOBAL_SLIPPAGE))) - ) revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); - } - + bytes4 rebalanceToSelector = _parseSelectorMem(rebalanceToCallData); /// @dev step 3: rebalance into a new superform with rebalanceCallData - if (!whitelistedSelectors[Actions.DEPOSIT][_parseSelectorMem(rebalanceToCallData)]) { + if (!whitelistedSelectors[Actions.DEPOSIT][rebalanceToSelector]) { revert INVALID_DEPOSIT_SELECTOR(); } + uint256 amountIn; + bool containsSwapData; + + if (rebalanceToSelector == IBaseRouter.singleDirectSingleVaultDeposit.selector) { + SingleVaultSFData memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData; + (amountIn, containsSwapData) = _takeAmountIn(sfData.liqRequest, sfData.amount); + } else if (rebalanceToSelector == IBaseRouter.singleXChainSingleVaultDeposit.selector) { + SingleVaultSFData memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (SingleXChainSingleVaultStateReq)).superformData; + (amountIn, containsSwapData) = _takeAmountIn(sfData.liqRequest, sfData.amount); + } else if (rebalanceToSelector == IBaseRouter.singleDirectMultiVaultDeposit.selector) { + MultiVaultSFData memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectMultiVaultStateReq)).superformData; + uint256 len = sfData.liqRequests.length; + uint256 amountInTemp; + for (uint256 i; i < len; ++i) { + (amountInTemp, containsSwapData) = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); + amountIn += amountInTemp; + } + } else if (rebalanceToSelector == IBaseRouter.singleXChainMultiVaultDeposit.selector) { + MultiVaultSFData memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (SingleXChainMultiVaultStateReq)).superformsData; + uint256 len = sfData.liqRequests.length; + uint256 amountInTemp; + for (uint256 i; i < len; ++i) { + (amountInTemp, containsSwapData) = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); + amountIn += amountInTemp; + } + } else if (rebalanceToSelector == IBaseRouter.multiDstSingleVaultDeposit.selector) { + SingleVaultSFData[] memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (MultiDstSingleVaultStateReq)).superformsData; + uint256 lenDst = sfData.length; + uint256 amountInTemp; + for (uint256 i; i < lenDst; ++i) { + (amountInTemp, containsSwapData) = _takeAmountIn(sfData[i].liqRequest, sfData[i].amount); + amountIn += amountInTemp; + } + } else if (rebalanceToSelector == IBaseRouter.multiDstMultiVaultDeposit.selector) { + MultiVaultSFData[] memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (MultiDstMultiVaultStateReq)).superformsData; + uint256 lenDst = sfData.length; + uint256 amountInTemp; + for (uint256 i; i < lenDst; ++i) { + uint256 len = sfData[i].liqRequests.length; + for (uint256 j; j < len; ++j) { + (amountInTemp, containsSwapData) = _takeAmountIn(sfData[i].liqRequests[j], sfData[i].amounts[j]); + amountIn += amountInTemp; + } + } + } + + if (containsSwapData) { + if (ENTIRE_SLIPPAGE * amountToDeposit < ((amountIn * (ENTIRE_SLIPPAGE - GLOBAL_SLIPPAGE)))) { + revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); + } + } + _deposit(router_, interimAsset, amountIn, args.rebalanceToMsgValue, rebalanceToCallData); } + function _takeAmountIn( + LiqRequest memory liqReq, + uint256 sfDataAmount + ) + internal + view + returns (uint256 amountIn, bool containsSwapData) + { + bytes memory txData = liqReq.txData; + if (txData.length == 0) { + amountIn = sfDataAmount; + } else { + amountIn = IBridgeValidator(superRegistry.getBridgeValidator(liqReq.bridgeId)).decodeAmountIn(txData, false); + containsSwapData = true; + } + } + function _transferSuperPositions( address superPositions_, address router_, From b8036d323004790a2ed37761e131cd686bcd92d3 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:14:15 +0200 Subject: [PATCH 11/44] refactor: rm global slippage setter in constructor --- src/router-plus/SuperformRouterPlus.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 1f9217347..b806744ed 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -35,9 +35,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { - GLOBAL_SLIPPAGE = 10; - } + constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) {} ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // From 25193dcb3bf3f5b87a1e9f7f54ce79ab51b4c956 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:14:35 +0200 Subject: [PATCH 12/44] refactor: set global slippage in setUp() --- test/utils/BaseSetup.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/utils/BaseSetup.sol b/test/utils/BaseSetup.sol index 95770586c..dea923a1c 100644 --- a/test/utils/BaseSetup.sol +++ b/test/utils/BaseSetup.sol @@ -1209,6 +1209,10 @@ abstract contract BaseSetup is StdInvariant, Test { vars.superformRouterPlus = address(new SuperformRouterPlus{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperformRouterPlus"))] = vars.superformRouterPlus; + /// Set the global slippage + SuperformRouterPlus(vars.superformRouterPlus).setGlobalSlippage(100); + + /// @dev deploy Superform Router Plus Async vars.superformRouterPlusAsync = address(new SuperformRouterPlusAsync{ salt: salt }(vars.superRegistry)); contracts[vars.chainId][bytes32(bytes("SuperformRouterPlusAsync"))] = vars.superformRouterPlusAsync; From c398275ca32ccfa33ed58f7deed2b86785072a50 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:48:51 +0200 Subject: [PATCH 13/44] reorder test_revert_dispatchPayload_invalidCaller() to revert correctly --- .../fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol b/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol index 0558f08bd..d919b8a6e 100644 --- a/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol +++ b/test/fuzz/crosschain-data/adapters/HyperlaneImplementation.t.sol @@ -114,7 +114,6 @@ contract HyperlaneImplementationTest is CommonProtocolActions { (ambMessage, ambExtraData, coreStateRegistry) = setupBroadcastPayloadAMBData(users[userIndex], address(hyperlaneImplementation)); - vm.expectRevert(Error.NOT_STATE_REGISTRY.selector); vm.assume(malice_ != getContract(ETH, "CoreStateRegistry")); vm.assume(malice_ != getContract(ETH, "TimelockStateRegistry")); vm.assume(malice_ != getContract(ETH, "BroadcastRegistry")); @@ -122,6 +121,7 @@ contract HyperlaneImplementationTest is CommonProtocolActions { vm.deal(malice_, 100 ether); vm.prank(malice_); + vm.expectRevert(Error.NOT_STATE_REGISTRY.selector); hyperlaneImplementation.dispatchPayload{ value: 0.1 ether }( users[userIndex], chainIds[5], abi.encode(ambMessage), abi.encode(ambExtraData) ); From 9a4c4633b97aff87044a711751cf0fc9b6b623c5 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:50:30 +0200 Subject: [PATCH 14/44] chore: update test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector() --- .../router-plus/SuperformRouterPlus.t.sol | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index d24368249..c56fdd98d 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -8,6 +8,7 @@ import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAs import { IBaseSuperformRouterPlus } from "src/interfaces/IBaseSuperformRouterPlus.sol"; import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +import { MultiVaultSFData } from "src/types/DataTypes.sol"; contract RejectEther { // This function will revert when called, simulating a contract that can't receive native tokens @@ -503,6 +504,177 @@ contract SuperformRouterPlusTest is ProtocolActions { vm.stopPrank(); } + function test_rebalanceSinglePosition_invalidDepositSelector() public { + vm.startPrank(deployer); + + _directDeposit(superformId1); + + ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = + _buildRebalanceSinglePositionToOneVaultArgs(deployer); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + + args.rebalanceToCallData = abi.encodeWithSelector(bytes4(keccak256("invalidSelector()"))); + + vm.expectRevert(ISuperformRouterPlus.INVALID_DEPOSIT_SELECTOR.selector); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + + vm.stopPrank(); + } + + function test_rebalanceSinglePosition_noSwapData() public { + vm.startPrank(deployer); + + _directDeposit(superformId1); + + ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = + _buildRebalanceSinglePositionToOneVaultArgs(deployer); + SingleVaultSFData memory sfData = + abi.decode(_parseCallData(args.rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData; + bytes memory emptyData; + sfData.liqRequest.txData = emptyData; + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); + + assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + } + + function test_rebalanceSinglePosition_singleDirectSingleVaultDepositSelector() public { + vm.startPrank(deployer); + + _directDeposit(superformId1); + + ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = + _buildRebalanceSinglePositionToOneVaultArgs(deployer); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + + vm.stopPrank(); + + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); + + assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + } + + function test_rebalanceSinglePosition_singleXChainSingleVaultDepositSelector() public { + vm.startPrank(deployer); + + _directDeposit(superformId1); + + ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = + _buildRebalanceSinglePositionToOneVaultArgs(deployer); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); + + assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + } + + function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { + + } + + function test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() public { + + } + + function test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector() public { + vm.startPrank(deployer); + + _directDeposit(superformId1); + _directDeposit(superformId2); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); + + IBaseSuperformRouterPlus.XChainRebalanceData memory data = IBaseSuperformRouterPlus.XChainRebalanceData({ + rebalanceSelector: IBaseRouter.multiDstMultiVaultDeposit.selector, + interimAsset: getContract(SOURCE_CHAIN, "DAI"), + slippage: 300, + expectedAmountInterimAsset: 3e18, + rebalanceToAmbIds: new uint8[][](0), + rebalanceToDstChainIds: new uint64[](0), + rebalanceToSfData: abi.encode( + MultiVaultSFData({ + superformIds: new uint256[](2), + amounts: new uint256[](2), + outputAmounts: new uint256[](2), + maxSlippages: new uint256[](2), + liqRequests: new LiqRequest[](2), + permit2data: "", + hasDstSwaps: new bool[](2), + retain4626s: new bool[](2), + receiverAddress: address(deployer), + receiverAddressSP: address(deployer), + extraFormData: "" + }) + ) + }); + + MultiVaultSFData memory sfData = abi.decode(data.rebalanceToSfData, (MultiVaultSFData)); + sfData.superformIds[0] = 3; + sfData.superformIds[1] = 4; + sfData.amounts[0] = 1.5e18; + sfData.amounts[1] = 1.5e18; + sfData.outputAmounts[0] = 1.5e18; + sfData.outputAmounts[1] = 1.5e18; + sfData.maxSlippages[0] = 300; + sfData.maxSlippages[1] = 300; + data.rebalanceToSfData = abi.encode(sfData); + + MultiDstMultiVaultStateReq memory req = MultiDstMultiVaultStateReq({ + ambIds: new uint8[][](2), + dstChainIds: new uint64[](2), + superformsData: new MultiVaultSFData[](1) + }); + req.ambIds[0] = new uint8[](2); + req.ambIds[0][0] = 1; + req.ambIds[0][1] = 2; + req.dstChainIds[0] = ETH; + req.dstChainIds[1] = OP; + req.superformsData[0] = sfData; + + //uint256 previewRedeemAmount1 = IBaseForm(superform1).previewRedeemFrom(req.superformsData[0].sharesToRedeem); + + //uint256 previewRedeemAmount2 = IBaseForm(superform2).previewRedeemFrom(req.superformsData[0].sharesToRedeem); + + uint256[] memory sharesToRedeem = new uint256[](2); + sharesToRedeem[0] = 10_000; + sharesToRedeem[1] = 10_000; + + uint256[] memory ids = new uint256[](2); + ids[0] = superformId1; + ids[1] = superformId2; + + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory positionArgs = ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs({ + ids: ids, + sharesToRedeem: sharesToRedeem, + expectedAmountToReceivePostRebalanceFrom: 10_000, + rebalanceFromMsgValue: 1 ether, + rebalanceToMsgValue: 1 ether, + interimAsset: getContract(SOURCE_CHAIN, "DAI"), + slippage: 300, + receiverAddressSP: address(deployer), + callData: abi.encode(req), + rebalanceToCallData: data.rebalanceToSfData + }); + + + + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 5 ether }(positionArgs); + vm.stopPrank(); + + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); + + assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + } + function test_refundUnusedAndResetApprovals_failedToSendNative() public { address rejectEther = address(new RejectEther()); deal(rejectEther, 3 ether); From 9f02765812f98d98ce8a8c9023271f9f22504edf Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Fri, 25 Oct 2024 13:50:33 +0200 Subject: [PATCH 15/44] chore: update test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index c56fdd98d..fbdb90bce 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -664,8 +664,6 @@ contract SuperformRouterPlusTest is ProtocolActions { callData: abi.encode(req), rebalanceToCallData: data.rebalanceToSfData }); - - SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 5 ether }(positionArgs); vm.stopPrank(); From 98174725d3a2d6189c0a0b807368f99619e12c15 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:25:26 +0100 Subject: [PATCH 16/44] fix: simplify test structure --- Makefile | 2 +- .../router-plus/SuperformRouterPlus.t.sol | 118 ++++++++---------- 2 files changed, 53 insertions(+), 67 deletions(-) diff --git a/Makefile b/Makefile index dfc8845e4..54531f8a7 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ build-sizes: ## Builds the project and shows sizes .PHONY: test-vvv test-vvv: ## Runs tests with verbose output - forge test --match-contract SDMVW0TokenInputNoSlippageAMB1323 --evm-version cancun -vvv + forge test --match-test test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector --evm-version cancun -vvv .PHONY: ftest ftest: ## Runs tests with cancun evm version diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index fbdb90bce..572db3438 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -530,7 +530,7 @@ contract SuperformRouterPlusTest is ProtocolActions { ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToOneVaultArgs(deployer); SingleVaultSFData memory sfData = - abi.decode(_parseCallData(args.rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData; + abi.decode(_parseCallData(args.rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData; bytes memory emptyData; sfData.liqRequest.txData = emptyData; @@ -576,13 +576,9 @@ contract SuperformRouterPlusTest is ProtocolActions { assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } - function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { + function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { } - } - - function test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() public { - - } + function test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() public { } function test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector() public { vm.startPrank(deployer); @@ -593,66 +589,56 @@ contract SuperformRouterPlusTest is ProtocolActions { SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); - IBaseSuperformRouterPlus.XChainRebalanceData memory data = IBaseSuperformRouterPlus.XChainRebalanceData({ - rebalanceSelector: IBaseRouter.multiDstMultiVaultDeposit.selector, - interimAsset: getContract(SOURCE_CHAIN, "DAI"), - slippage: 300, - expectedAmountInterimAsset: 3e18, - rebalanceToAmbIds: new uint8[][](0), - rebalanceToDstChainIds: new uint64[](0), - rebalanceToSfData: abi.encode( - MultiVaultSFData({ - superformIds: new uint256[](2), - amounts: new uint256[](2), - outputAmounts: new uint256[](2), - maxSlippages: new uint256[](2), - liqRequests: new LiqRequest[](2), - permit2data: "", - hasDstSwaps: new bool[](2), - retain4626s: new bool[](2), - receiverAddress: address(deployer), - receiverAddressSP: address(deployer), - extraFormData: "" - }) - ) - }); - - MultiVaultSFData memory sfData = abi.decode(data.rebalanceToSfData, (MultiVaultSFData)); - sfData.superformIds[0] = 3; - sfData.superformIds[1] = 4; - sfData.amounts[0] = 1.5e18; - sfData.amounts[1] = 1.5e18; - sfData.outputAmounts[0] = 1.5e18; - sfData.outputAmounts[1] = 1.5e18; - sfData.maxSlippages[0] = 300; - sfData.maxSlippages[1] = 300; - data.rebalanceToSfData = abi.encode(sfData); - - MultiDstMultiVaultStateReq memory req = MultiDstMultiVaultStateReq({ - ambIds: new uint8[][](2), - dstChainIds: new uint64[](2), - superformsData: new MultiVaultSFData[](1) - }); - req.ambIds[0] = new uint8[](2); - req.ambIds[0][0] = 1; - req.ambIds[0][1] = 2; - req.dstChainIds[0] = ETH; - req.dstChainIds[1] = OP; - req.superformsData[0] = sfData; - - //uint256 previewRedeemAmount1 = IBaseForm(superform1).previewRedeemFrom(req.superformsData[0].sharesToRedeem); - - //uint256 previewRedeemAmount2 = IBaseForm(superform2).previewRedeemFrom(req.superformsData[0].sharesToRedeem); - uint256[] memory sharesToRedeem = new uint256[](2); - sharesToRedeem[0] = 10_000; - sharesToRedeem[1] = 10_000; + sharesToRedeem[0] = 1e18; + sharesToRedeem[1] = 1e18; uint256[] memory ids = new uint256[](2); ids[0] = superformId1; ids[1] = superformId2; - ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory positionArgs = ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs({ + uint8[][] memory ambIds_ = new uint8[][](2); + ambIds_[0] = new uint8[](2); + ambIds_[0][0] = AMBs[0]; + ambIds_[0][1] = AMBs[1]; + ambIds_[1] = new uint8[](2); + ambIds_[1][0] = AMBs[0]; + ambIds_[1][1] = AMBs[1]; + + uint64[] memory dstChainIds = new uint64[](2); + dstChainIds[0] = OP; + dstChainIds[1] = ARBI; + + MultiVaultSFData[] memory mvSfData = new MultiVaultSFData[](2); + mvSfData[0] = MultiVaultSFData({ + superformIds: new uint256[](2), + amounts: new uint256[](2), + outputAmounts: new uint256[](2), + maxSlippages: new uint256[](2), + liqRequests: new LiqRequest[](2), + permit2data: "", + hasDstSwaps: new bool[](2), + retain4626s: new bool[](2), + receiverAddress: address(deployer), + receiverAddressSP: address(deployer), + extraFormData: "" + }); + mvSfData[1] = MultiVaultSFData({ + superformIds: new uint256[](2), + amounts: new uint256[](2), + outputAmounts: new uint256[](2), + maxSlippages: new uint256[](2), + liqRequests: new LiqRequest[](2), + permit2data: "", + hasDstSwaps: new bool[](2), + retain4626s: new bool[](2), + receiverAddress: address(deployer), + receiverAddressSP: address(deployer), + extraFormData: "" + }); + MultiDstMultiVaultStateReq memory req = MultiDstMultiVaultStateReq(ambIds_, dstChainIds, mvSfData); + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory positionArgs = ISuperformRouterPlus + .RebalanceMultiPositionsSyncArgs({ ids: ids, sharesToRedeem: sharesToRedeem, expectedAmountToReceivePostRebalanceFrom: 10_000, @@ -661,10 +647,10 @@ contract SuperformRouterPlusTest is ProtocolActions { interimAsset: getContract(SOURCE_CHAIN, "DAI"), slippage: 300, receiverAddressSP: address(deployer), - callData: abi.encode(req), - rebalanceToCallData: data.rebalanceToSfData + callData: _callDataRebalanceFromTwoVaults(getContract(SOURCE_CHAIN, "DAI")), + rebalanceToCallData: abi.encodeCall(IBaseRouter.multiDstMultiVaultDeposit, req) }); - + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 5 ether }(positionArgs); vm.stopPrank(); @@ -4340,7 +4326,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_setGlobalSlippage() public { // Test invalid caller - vm.startPrank(address(12345)); + vm.startPrank(address(12_345)); vm.expectRevert(); SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(100); vm.stopPrank(); @@ -4348,7 +4334,7 @@ contract SuperformRouterPlusTest is ProtocolActions { // Test slippage greater than ENTIRE_SLIPPAGE vm.startPrank(deployer); vm.expectRevert(); - SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(1000000); + SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(1_000_000); vm.stopPrank(); // Test slippage 0 From bb0867a38821d5a96650ce8a9a2f49eeab258ae9 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Sat, 26 Oct 2024 10:31:35 +0200 Subject: [PATCH 17/44] fix: rm tests relating to disputeRefund() --- .../router-plus/SuperformRouterPlus.t.sol | 81 ++++++++++--------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 572db3438..c20a46009 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -1854,56 +1854,65 @@ contract SuperformRouterPlusTest is ProtocolActions { SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).completeCrossChainRebalance{ value: 1 ether }(completeArgs); vm.stopPrank(); - vm.expectRevert(Error.NOT_VALID_DISPUTER.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).disputeRefund(1); + // Step 5: Request refund - vm.startPrank(deployer); - vm.mockCall( - address(getContract(SOURCE_CHAIN, "SuperRegistry")), - abi.encodeWithSelector(ISuperRegistry.delay.selector), - abi.encode(0) - ); - vm.expectRevert(Error.DELAY_NOT_SET.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).disputeRefund(1); - vm.clearMockedCalls(); - - vm.warp(block.timestamp + 100 days); - vm.expectRevert(Error.DISPUTE_TIME_ELAPSED.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).disputeRefund(1); - - vm.warp(block.timestamp - 100 days); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).disputeRefund(1); + /// @dev testing invalid requester (not receiver) + vm.startPrank(address(222)); + vm.expectRevert(ISuperformRouterPlusAsync.INVALID_REQUESTER.selector); + SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).requestRefund(1, 100); + vm.stopPrank(); - vm.expectRevert(Error.DISPUTE_TIME_ELAPSED.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).disputeRefund(1); + // @dev testing refund amount exceeds expected amount + vm.startPrank(deployer); + vm.expectRevert(ISuperformRouterPlusAsync.REQUESTED_AMOUNT_TOO_HIGH.selector); + SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).requestRefund(1, 1000e18); vm.stopPrank(); - vm.expectRevert(ISuperformRouterPlusAsync.INVALID_PROPOSER.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).proposeRefund(1, completeArgs.amountReceivedInterimAsset); + /// @dev testing valid refund request + vm.prank(deployer); + SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).requestRefund(1, 100); - vm.startPrank(deployer); - vm.expectRevert(ISuperformRouterPlusAsync.INVALID_REFUND_DATA.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).proposeRefund(2, completeArgs.amountReceivedInterimAsset); + (,, uint256 requestedAmount) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); + assertEq(requestedAmount, 100); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).proposeRefund(1, completeArgs.amountReceivedInterimAsset); + (, address refundToken,) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); + assertEq(refundToken, address(args.interimAsset)); - vm.expectRevert(ISuperformRouterPlusAsync.REFUND_ALREADY_PROPOSED.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).proposeRefund(1, completeArgs.amountReceivedInterimAsset); + // Step 6: Approve refund - vm.expectRevert(ISuperformRouterPlusAsync.IN_DISPUTE_PHASE.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).finalizeRefund(1); + /// @dev testing invalid approver (not core state registry) + vm.startPrank(address(1234)); + vm.expectRevert(ISuperformRouterPlusAsync.NOT_CORE_STATE_REGISTRY_RESCUER.selector); + SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).approveRefund(1); + vm.stopPrank(); - (, address refundToken,,) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); + /// @dev testing valid refund approval uint256 balanceBefore = MockERC20(refundToken).balanceOf(deployer); + uint256 routerBalanceBefore = MockERC20(refundToken).balanceOf(address(ROUTER_PLUS_ASYNC_SOURCE)); + vm.startPrank(deployer); + SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).approveRefund(1); + vm.stopPrank(); - vm.warp(block.timestamp + 100 days); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).finalizeRefund(1); uint256 balanceAfter = MockERC20(refundToken).balanceOf(deployer); - assertGt(balanceAfter, balanceBefore); + assertEq(MockERC20(refundToken).balanceOf(address(ROUTER_PLUS_ASYNC_SOURCE)), routerBalanceBefore - 100); + assertEq(MockERC20(refundToken).balanceOf(address(deployer)), balanceBefore + 100); + + (, address interimToken,) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); + assertEq(interimToken, address(0)); + + (, address receiver,) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); + assertEq(receiver, address(0)); - vm.expectRevert(ISuperformRouterPlusAsync.IN_DISPUTE_PHASE.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).finalizeRefund(1); + (,, uint256 updatedRequestedAmount) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); + assertEq(updatedRequestedAmount, 0); + vm.stopPrank(); + + /// @dev testing refund already approved + vm.startPrank(deployer); + vm.expectRevert(ISuperformRouterPlusAsync.REFUND_ALREADY_APPROVED.selector); + SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).approveRefund(1); + vm.stopPrank(); } function test_crossChainRebalance_negativeSlippage() public { From 260f2a16d836d688641d8ae9e299ef89aa307fcb Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:49:05 +0200 Subject: [PATCH 18/44] fix: rm overrides --- src/router-plus/SuperformRouterPlus.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index b806744ed..ecb460009 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -357,7 +357,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { } /// @inheritdoc ISuperformRouterPlus - function deposit4626(address vault_, Deposit4626Args calldata args) external payable override { + function deposit4626(address vault_, Deposit4626Args calldata args) external payable { _transferERC20In(IERC20(vault_), args.receiverAddressSP, args.amount); IERC4626 vault = IERC4626(vault_); address assetAdr = vault.asset(); @@ -394,7 +394,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { } /// @inheritdoc ISuperformRouterPlus - function setGlobalSlippage(uint256 slippage_) external override { + function setGlobalSlippage(uint256 slippage_) external { if (!_hasRole(keccak256("EMERGENCY_ADMIN_ROLE"), msg.sender)) { revert Error.NOT_PRIVILEGED_CALLER(keccak256("EMERGENCY_ADMIN_ROLE")); } From e246f497dd3ba9a71f7b06c91d84c8bb5bb08717 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Sat, 26 Oct 2024 13:56:40 +0200 Subject: [PATCH 19/44] fix: update liqReqs for multidstmultivault rebalance --- .../router-plus/SuperformRouterPlus.t.sol | 126 +++++++++--------- 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index c20a46009..f26242a45 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -623,6 +623,39 @@ contract SuperformRouterPlusTest is ProtocolActions { receiverAddressSP: address(deployer), extraFormData: "" }); + + mvSfData[0].superformIds[0] = superformId1; + mvSfData[0].superformIds[1] = superformId2; + mvSfData[0].amounts[0] = 1e18; + mvSfData[0].amounts[1] = 1e18; + mvSfData[0].outputAmounts[0] = 1e18; + mvSfData[0].outputAmounts[1] = 1e18; + mvSfData[0].maxSlippages[0] = 300; + mvSfData[0].maxSlippages[1] = 300; + mvSfData[0].liqRequests[0] = LiqRequest({ + txData: "", + token: address(0), + interimToken: address(0), + bridgeId: 0, + liqDstChainId: 0, + nativeAmount: 0 + }); + mvSfData[0].liqRequests[1] = LiqRequest({ + txData: "", + token: address(0), + interimToken: address(0), + bridgeId: 0, + liqDstChainId: 0, + nativeAmount: 0 + }); + mvSfData[0].hasDstSwaps[0] = false; + mvSfData[0].hasDstSwaps[1] = false; + mvSfData[0].retain4626s[0] = false; + mvSfData[0].retain4626s[1] = false; + mvSfData[0].receiverAddress = address(deployer); + mvSfData[0].receiverAddressSP = address(deployer); + mvSfData[0].extraFormData = ""; + mvSfData[1] = MultiVaultSFData({ superformIds: new uint256[](2), amounts: new uint256[](2), @@ -636,6 +669,39 @@ contract SuperformRouterPlusTest is ProtocolActions { receiverAddressSP: address(deployer), extraFormData: "" }); + + mvSfData[1].superformIds[0] = superformId1; + mvSfData[1].superformIds[1] = superformId2; + mvSfData[1].amounts[0] = 1e18; + mvSfData[1].amounts[1] = 1e18; + mvSfData[1].outputAmounts[0] = 1e18; + mvSfData[1].outputAmounts[1] = 1e18; + mvSfData[1].maxSlippages[0] = 300; + mvSfData[1].maxSlippages[1] = 300; + mvSfData[1].liqRequests[0] = LiqRequest({ + txData: "", + token: address(0), + interimToken: address(0), + bridgeId: 0, + liqDstChainId: 0, + nativeAmount: 0 + }); + mvSfData[1].liqRequests[1] = LiqRequest({ + txData: "", + token: address(0), + interimToken: address(0), + bridgeId: 0, + liqDstChainId: 0, + nativeAmount: 0 + }); + mvSfData[1].hasDstSwaps[0] = false; + mvSfData[1].hasDstSwaps[1] = false; + mvSfData[1].retain4626s[0] = false; + mvSfData[1].retain4626s[1] = false; + mvSfData[1].receiverAddress = address(deployer); + mvSfData[1].receiverAddressSP = address(deployer); + mvSfData[1].extraFormData = ""; + MultiDstMultiVaultStateReq memory req = MultiDstMultiVaultStateReq(ambIds_, dstChainIds, mvSfData); ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory positionArgs = ISuperformRouterPlus .RebalanceMultiPositionsSyncArgs({ @@ -1853,66 +1919,6 @@ contract SuperformRouterPlusTest is ProtocolActions { completeArgs.amountReceivedInterimAsset = completeArgs.amountReceivedInterimAsset / 3; SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).completeCrossChainRebalance{ value: 1 ether }(completeArgs); vm.stopPrank(); - - // Step 5: Request refund - - /// @dev testing invalid requester (not receiver) - vm.startPrank(address(222)); - vm.expectRevert(ISuperformRouterPlusAsync.INVALID_REQUESTER.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).requestRefund(1, 100); - vm.stopPrank(); - - // @dev testing refund amount exceeds expected amount - vm.startPrank(deployer); - vm.expectRevert(ISuperformRouterPlusAsync.REQUESTED_AMOUNT_TOO_HIGH.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).requestRefund(1, 1000e18); - vm.stopPrank(); - - /// @dev testing valid refund request - vm.prank(deployer); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).requestRefund(1, 100); - - (,, uint256 requestedAmount) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); - assertEq(requestedAmount, 100); - - (, address refundToken,) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); - assertEq(refundToken, address(args.interimAsset)); - - // Step 6: Approve refund - - /// @dev testing invalid approver (not core state registry) - vm.startPrank(address(1234)); - vm.expectRevert(ISuperformRouterPlusAsync.NOT_CORE_STATE_REGISTRY_RESCUER.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).approveRefund(1); - vm.stopPrank(); - - /// @dev testing valid refund approval - uint256 balanceBefore = MockERC20(refundToken).balanceOf(deployer); - uint256 routerBalanceBefore = MockERC20(refundToken).balanceOf(address(ROUTER_PLUS_ASYNC_SOURCE)); - vm.startPrank(deployer); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).approveRefund(1); - vm.stopPrank(); - - uint256 balanceAfter = MockERC20(refundToken).balanceOf(deployer); - assertGt(balanceAfter, balanceBefore); - assertEq(MockERC20(refundToken).balanceOf(address(ROUTER_PLUS_ASYNC_SOURCE)), routerBalanceBefore - 100); - assertEq(MockERC20(refundToken).balanceOf(address(deployer)), balanceBefore + 100); - - (, address interimToken,) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); - assertEq(interimToken, address(0)); - - (, address receiver,) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); - assertEq(receiver, address(0)); - - (,, uint256 updatedRequestedAmount) = SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).refunds(1); - assertEq(updatedRequestedAmount, 0); - vm.stopPrank(); - - /// @dev testing refund already approved - vm.startPrank(deployer); - vm.expectRevert(ISuperformRouterPlusAsync.REFUND_ALREADY_APPROVED.selector); - SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).approveRefund(1); - vm.stopPrank(); } function test_crossChainRebalance_negativeSlippage() public { From c9f1be4a9901cfe517f19ab35af3da22bc71bda3 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:57:07 +0200 Subject: [PATCH 20/44] chore: add test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() --- .../router-plus/SuperformRouterPlus.t.sol | 460 ++++++++++++------ 1 file changed, 312 insertions(+), 148 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index f26242a45..088318f29 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -556,19 +556,22 @@ contract SuperformRouterPlusTest is ProtocolActions { vm.stopPrank(); assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); - - assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } - function test_rebalanceSinglePosition_singleXChainSingleVaultDepositSelector() public { + + + // Deposit into multiple vaults on one chain with tokens from another chain. + function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { vm.startPrank(deployer); _directDeposit(superformId1); + _directDeposit(superformId2); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = - _buildRebalanceSinglePositionToOneVaultArgs(deployer); + _buildRebalanceSinglePositionToTwoVaultsArgs(); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); @@ -576,153 +579,270 @@ contract SuperformRouterPlusTest is ProtocolActions { assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } - function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { } - + // Deposit into a single vault on multiple different chains with tokens from any chain. function test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() public { } function test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector() public { - vm.startPrank(deployer); - - _directDeposit(superformId1); - _directDeposit(superformId2); - - SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); - SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); - - uint256[] memory sharesToRedeem = new uint256[](2); - sharesToRedeem[0] = 1e18; - sharesToRedeem[1] = 1e18; - - uint256[] memory ids = new uint256[](2); - ids[0] = superformId1; - ids[1] = superformId2; - - uint8[][] memory ambIds_ = new uint8[][](2); - ambIds_[0] = new uint8[](2); - ambIds_[0][0] = AMBs[0]; - ambIds_[0][1] = AMBs[1]; - ambIds_[1] = new uint8[](2); - ambIds_[1][0] = AMBs[0]; - ambIds_[1][1] = AMBs[1]; - - uint64[] memory dstChainIds = new uint64[](2); - dstChainIds[0] = OP; - dstChainIds[1] = ARBI; - - MultiVaultSFData[] memory mvSfData = new MultiVaultSFData[](2); - mvSfData[0] = MultiVaultSFData({ - superformIds: new uint256[](2), - amounts: new uint256[](2), - outputAmounts: new uint256[](2), - maxSlippages: new uint256[](2), - liqRequests: new LiqRequest[](2), - permit2data: "", - hasDstSwaps: new bool[](2), - retain4626s: new bool[](2), - receiverAddress: address(deployer), - receiverAddressSP: address(deployer), - extraFormData: "" - }); - - mvSfData[0].superformIds[0] = superformId1; - mvSfData[0].superformIds[1] = superformId2; - mvSfData[0].amounts[0] = 1e18; - mvSfData[0].amounts[1] = 1e18; - mvSfData[0].outputAmounts[0] = 1e18; - mvSfData[0].outputAmounts[1] = 1e18; - mvSfData[0].maxSlippages[0] = 300; - mvSfData[0].maxSlippages[1] = 300; - mvSfData[0].liqRequests[0] = LiqRequest({ - txData: "", - token: address(0), - interimToken: address(0), - bridgeId: 0, - liqDstChainId: 0, - nativeAmount: 0 - }); - mvSfData[0].liqRequests[1] = LiqRequest({ - txData: "", - token: address(0), - interimToken: address(0), - bridgeId: 0, - liqDstChainId: 0, - nativeAmount: 0 - }); - mvSfData[0].hasDstSwaps[0] = false; - mvSfData[0].hasDstSwaps[1] = false; - mvSfData[0].retain4626s[0] = false; - mvSfData[0].retain4626s[1] = false; - mvSfData[0].receiverAddress = address(deployer); - mvSfData[0].receiverAddressSP = address(deployer); - mvSfData[0].extraFormData = ""; - - mvSfData[1] = MultiVaultSFData({ - superformIds: new uint256[](2), - amounts: new uint256[](2), - outputAmounts: new uint256[](2), - maxSlippages: new uint256[](2), - liqRequests: new LiqRequest[](2), - permit2data: "", - hasDstSwaps: new bool[](2), - retain4626s: new bool[](2), - receiverAddress: address(deployer), - receiverAddressSP: address(deployer), - extraFormData: "" - }); - - mvSfData[1].superformIds[0] = superformId1; - mvSfData[1].superformIds[1] = superformId2; - mvSfData[1].amounts[0] = 1e18; - mvSfData[1].amounts[1] = 1e18; - mvSfData[1].outputAmounts[0] = 1e18; - mvSfData[1].outputAmounts[1] = 1e18; - mvSfData[1].maxSlippages[0] = 300; - mvSfData[1].maxSlippages[1] = 300; - mvSfData[1].liqRequests[0] = LiqRequest({ - txData: "", - token: address(0), - interimToken: address(0), - bridgeId: 0, - liqDstChainId: 0, - nativeAmount: 0 - }); - mvSfData[1].liqRequests[1] = LiqRequest({ - txData: "", - token: address(0), - interimToken: address(0), - bridgeId: 0, - liqDstChainId: 0, - nativeAmount: 0 - }); - mvSfData[1].hasDstSwaps[0] = false; - mvSfData[1].hasDstSwaps[1] = false; - mvSfData[1].retain4626s[0] = false; - mvSfData[1].retain4626s[1] = false; - mvSfData[1].receiverAddress = address(deployer); - mvSfData[1].receiverAddressSP = address(deployer); - mvSfData[1].extraFormData = ""; - - MultiDstMultiVaultStateReq memory req = MultiDstMultiVaultStateReq(ambIds_, dstChainIds, mvSfData); - ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory positionArgs = ISuperformRouterPlus - .RebalanceMultiPositionsSyncArgs({ - ids: ids, - sharesToRedeem: sharesToRedeem, - expectedAmountToReceivePostRebalanceFrom: 10_000, - rebalanceFromMsgValue: 1 ether, - rebalanceToMsgValue: 1 ether, - interimAsset: getContract(SOURCE_CHAIN, "DAI"), - slippage: 300, - receiverAddressSP: address(deployer), - callData: _callDataRebalanceFromTwoVaults(getContract(SOURCE_CHAIN, "DAI")), - rebalanceToCallData: abi.encodeCall(IBaseRouter.multiDstMultiVaultDeposit, req) - }); - - SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 5 ether }(positionArgs); - vm.stopPrank(); - - assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); - - assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + // //vm.startPrank(deployer); + // vm.selectFork(FORKS[SOURCE_CHAIN]); + + // uint64 REBALANCE_FROM_1 = ETH; + // uint64 REBALANCE_FROM_2 = OP; + // uint64 REBALANCE_TO = OP; + + // deal(getContract(SOURCE_CHAIN, "DAI"), deployer, 10e18); + + // vm.prank(deployer); + // _xChainDeposit(superformId5ETH, REBALANCE_FROM_1, 1); + + // vm.prank(deployer); + // _xChainDeposit(superformId6ETH, REBALANCE_FROM_1, 2); + + // vm.prank(deployer); + // _xChainDeposit(superformId4OP, REBALANCE_FROM_2, 1); + + // vm.selectFork(FORKS[SOURCE_CHAIN]); + // ISuperformRouterPlus.InitiateXChainRebalanceMultiArgs memory rebalanceArgs = + // _buildInitiateXChainRebalanceMultiDstToMultiArgs(REBALANCE_FROM_1, REBALANCE_FROM_2, REBALANCE_TO); + + // vm.prank(deployer); + // SuperPositions(SUPER_POSITIONS_SOURCE).setApprovalForAll(ROUTER_PLUS_SOURCE, true); + + // // vm.startPrank(deployer); + // // _directDeposit(superformId1); + // // _directDeposit(superformId2); + // // vm.stopPrank(); + + // // Setup: Create two destination superforms on the same chain + + // MultiVaultSFData memory sfData = MultiVaultSFData({ + // superformIds: new uint256[](2), + // amounts: new uint256[](2), + // outputAmounts: new uint256[](2), + // maxSlippages: new uint256[](2), + // liqRequests: new LiqRequest[](2), + // permit2data: "", + // hasDstSwaps: new bool[](2), + // retain4626s: new bool[](2), + // receiverAddress: address(deployer), + // receiverAddressSP: address(deployer), + // extraFormData: "" + // }); + + // sfData.superformIds[0] = superformId1; + // sfData.superformIds[1] = superformId2; + // sfData.amounts[0] = 5e17; // 0.5 ether + // sfData.amounts[1] = 5e17; // 0.5 ether + // sfData.outputAmounts[0] = 5e17; + // sfData.outputAmounts[1] = 5e17; + // sfData.maxSlippages[0] = 100; + // sfData.maxSlippages[1] = 100; + + // MultiVaultSFData[] memory multiVaultSFData = new MultiVaultSFData[](1); + // multiVaultSFData[0] = sfData; + + // address interimAsset = getContract(SOURCE_CHAIN, "DAI"); + + // for (uint256 i = 0; i < 2; i++) { + // sfData.liqRequests[i] = LiqRequest({ + // txData: "", + // token: interimAsset, + // interimToken: address(0), + // bridgeId: 0, + // liqDstChainId: SOURCE_CHAIN, + // nativeAmount: 0 + // }); + // } + + // // IBaseSuperformRouterPlus.XChainRebalanceData memory data = IBaseSuperformRouterPlus.XChainRebalanceData({ + // // rebalanceSelector: IBaseRouter.multiDstMultiVaultDeposit.selector, + // // interimAsset: interimAsset, + // // slippage: 100, + // // expectedAmountInterimAsset: 1e18, + // // rebalanceToAmbIds: new uint8[][](0), + // // rebalanceToDstChainIds: new uint64[](0), + // // rebalanceToSfData: abi.encode(multiVaultSFData) + // // }); + + // // vm.startPrank(ROUTER_PLUS_SOURCE); + // // SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).setXChainRebalanceCallData(deployer, 1, data); + // // vm.stopPrank(); + + // uint256[][] memory newAmounts = new uint256[][](1); + // newAmounts[0] = new uint256[](2); + // newAmounts[0][0] = 5e17; + // newAmounts[0][1] = 5e17; + + // uint256[][] memory newOutputAmounts = new uint256[][](1); + // newOutputAmounts[0] = new uint256[](2); + // newOutputAmounts[0][0] = 5e17; + // newOutputAmounts[0][1] = 5e17; + + // // LiqRequest[][] memory liqRequests = new LiqRequest[][](0); + + // // ISuperformRouterPlusAsync.CompleteCrossChainRebalanceArgs memory completeArgs = ISuperformRouterPlusAsync + // // .CompleteCrossChainRebalanceArgs({ + // // receiverAddressSP: address(deployer), + // // routerPlusPayloadId: 1, + // // amountReceivedInterimAsset: 1e18, + // // newAmounts: newAmounts, + // // newOutputAmounts: newOutputAmounts, + // // liqRequests: liqRequests + // // }); + + // deal(interimAsset, address(ROUTER_PLUS_ASYNC_SOURCE), 1e18); + + // vm.startPrank(deployer); + // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); + // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); + + // uint256[] memory sharesToRedeem = new uint256[](2); + // sharesToRedeem[0] = 1e18; + // sharesToRedeem[1] = 1e18; + + // // uint256[] memory ids = new uint256[](2); + // // ids[0] = superformId1; + // // ids[1] = superformId2; + + // uint8[][] memory ambIds_ = new uint8[][](2); + // ambIds_[0] = new uint8[](2); + // ambIds_[0][0] = AMBs[0]; + // ambIds_[0][1] = AMBs[1]; + // ambIds_[1] = new uint8[](2); + // ambIds_[1][0] = AMBs[0]; + // ambIds_[1][1] = AMBs[1]; + + // uint64[] memory dstChainIds = new uint64[](2); + // dstChainIds[0] = OP; + // dstChainIds[1] = ETH; + + // // MultiVaultSFData[] memory mvSfData = new MultiVaultSFData[](2); + // // mvSfData[0] = MultiVaultSFData({ + // // superformIds: new uint256[](2), + // // amounts: new uint256[](2), + // // outputAmounts: new uint256[](2), + // // maxSlippages: new uint256[](2), + // // liqRequests: new LiqRequest[](2), + // // permit2data: "", + // // hasDstSwaps: new bool[](2), + // // retain4626s: new bool[](2), + // // receiverAddress: address(deployer), + // // receiverAddressSP: address(deployer), + // // extraFormData: "" + // // }); + + // // mvSfData[0].superformIds[0] = superformId1; + // // mvSfData[0].superformIds[1] = superformId2; + // // mvSfData[0].amounts[0] = 1e18; + // // mvSfData[0].amounts[1] = 1e18; + // // mvSfData[0].outputAmounts[0] = 1e18; + // // mvSfData[0].outputAmounts[1] = 1e18; + // // mvSfData[0].maxSlippages[0] = 300; + // // mvSfData[0].maxSlippages[1] = 300; + // // mvSfData[0].liqRequests[0] = LiqRequest({ + // // txData: "", + // // token: address(0), + // // interimToken: address(0), + // // bridgeId: 0, + // // liqDstChainId: 0, + // // nativeAmount: 0 + // // }); + // // mvSfData[0].liqRequests[1] = LiqRequest({ + // // txData: "", + // // token: address(0), + // // interimToken: address(0), + // // bridgeId: 0, + // // liqDstChainId: 0, + // // nativeAmount: 0 + // // }); + // // mvSfData[0].hasDstSwaps[0] = false; + // // mvSfData[0].hasDstSwaps[1] = false; + // // mvSfData[0].retain4626s[0] = false; + // // mvSfData[0].retain4626s[1] = false; + // // mvSfData[0].receiverAddress = address(deployer); + // // mvSfData[0].receiverAddressSP = address(deployer); + // // mvSfData[0].extraFormData = ""; + + // // mvSfData[1] = MultiVaultSFData({ + // // superformIds: new uint256[](2), + // // amounts: new uint256[](2), + // // outputAmounts: new uint256[](2), + // // maxSlippages: new uint256[](2), + // // liqRequests: new LiqRequest[](2), + // // permit2data: "", + // // hasDstSwaps: new bool[](2), + // // retain4626s: new bool[](2), + // // receiverAddress: address(deployer), + // // receiverAddressSP: address(deployer), + // // extraFormData: "" + // // }); + + // // mvSfData[1].superformIds[0] = superformId1; + // // mvSfData[1].superformIds[1] = superformId2; + // // mvSfData[1].amounts[0] = 1e18; + // // mvSfData[1].amounts[1] = 1e18; + // // mvSfData[1].outputAmounts[0] = 1e18; + // // mvSfData[1].outputAmounts[1] = 1e18; + // // mvSfData[1].maxSlippages[0] = 300; + // // mvSfData[1].maxSlippages[1] = 300; + // // mvSfData[1].liqRequests[0] = LiqRequest({ + // // txData: "", + // // token: address(0), + // // interimToken: address(0), + // // bridgeId: 0, + // // liqDstChainId: 0, + // // nativeAmount: 0 + // // }); + // // mvSfData[1].liqRequests[1] = LiqRequest({ + // // txData: "", + // // token: address(0), + // // interimToken: address(0), + // // bridgeId: 0, + // // liqDstChainId: 0, + // // nativeAmount: 0 + // // }); + // // mvSfData[1].hasDstSwaps[0] = false; + // // mvSfData[1].hasDstSwaps[1] = false; + // // mvSfData[1].retain4626s[0] = false; + // // mvSfData[1].retain4626s[1] = false; + // // mvSfData[1].receiverAddress = address(deployer); + // // mvSfData[1].receiverAddressSP = address(deployer); + // // mvSfData[1].extraFormData = ""; + // // vm.stopPrank(); + + // // vm.startPrank(ROUTER_PLUS_SOURCE); + // // IBaseSuperformRouterPlus.XChainRebalanceData memory data = IBaseSuperformRouterPlus.XChainRebalanceData({ + // // rebalanceSelector: IBaseRouter.multiDstMultiVaultDeposit.selector, + // // interimAsset: address(0x678), + // // slippage: 600, + // // expectedAmountInterimAsset: 6e18, + // // rebalanceToAmbIds: ambIds_, + // // rebalanceToDstChainIds: dstChainIds, + // // rebalanceToSfData: abi.encode(mvSfData) + // // }); + + // vm.startPrank(deployer); + // MultiDstMultiVaultStateReq memory req = MultiDstMultiVaultStateReq(ambIds_, dstChainIds, multiVaultSFData); + // ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory positionArgs = ISuperformRouterPlus + // .RebalanceMultiPositionsSyncArgs({ + // ids: sfData.superformIds, + // sharesToRedeem: sharesToRedeem, + // expectedAmountToReceivePostRebalanceFrom: 10_000, + // rebalanceFromMsgValue: 1 ether, + // rebalanceToMsgValue: 1 ether, + // interimAsset: getContract(SOURCE_CHAIN, "DAI"), + // slippage: 300, + // receiverAddressSP: address(deployer), + // callData: _callDataRebalanceFromTwoVaults(getContract(SOURCE_CHAIN, "DAI")), + // rebalanceToCallData: abi.encodeCall(IBaseRouter.multiDstMultiVaultDeposit, req) + // }); + + // SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(positionArgs); + // vm.stopPrank(); + + // assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); + + // assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } function test_refundUnusedAndResetApprovals_failedToSendNative() public { @@ -2712,6 +2832,50 @@ contract SuperformRouterPlusTest is ProtocolActions { args.rebalanceToCallData = _callDataRebalanceToOneVaultxChain(totalAmountToDeposit, args.interimAsset); } + // function _buildRebalanceTwoPositionsToTwoVaultsXChainArgs() + // internal + // returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args, uint256[] calldata totalAmountToDeposit) + // { + // args.ids = new uint256[](2); + // args.ids[0] = superformId1; + // args.ids[1] = superformId2; + + // args.sharesToRedeem = new uint256[](2); + // args.sharesToRedeem[0] = SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1); + // args.sharesToRedeem[1] = SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2); + + // args.rebalanceFromMsgValue = 1 ether; + // args.rebalanceToMsgValue = 1 ether; + // args.interimAsset = getContract(SOURCE_CHAIN, "USDC"); + // args.slippage = 100; + // args.receiverAddressSP = deployer; + // args.callData = _callDataRebalanceFromTwoVaults(args.interimAsset); + + // uint256 decimal1 = MockERC20(getContract(SOURCE_CHAIN, "DAI")).decimals(); + // uint256 decimal2 = MockERC20(args.interimAsset).decimals(); + // uint256 previewRedeemAmount1 = IBaseForm(superform1).previewRedeemFrom(args.sharesToRedeem[0]); + + // uint256 expectedAmountToReceivePostRebalanceFrom1; + // if (decimal1 > decimal2) { + // expectedAmountToReceivePostRebalanceFrom1 = previewRedeemAmount1 / (10 ** (decimal1 - decimal2)); + // } else { + // expectedAmountToReceivePostRebalanceFrom1 = previewRedeemAmount1 * 10 ** (decimal2 - decimal1); + // } + + // uint256 previewRedeemAmount2 = IBaseForm(superform2).previewRedeemFrom(args.sharesToRedeem[1]); + + // uint256 expectedAmountToReceivePostRebalanceFrom2; + // if (decimal1 > decimal2) { + // expectedAmountToReceivePostRebalanceFrom2 = previewRedeemAmount2 / (10 ** (decimal1 - decimal2)); + // } else { + // expectedAmountToReceivePostRebalanceFrom2 = previewRedeemAmount2 * 10 ** (decimal2 - decimal1); + // } + + // totalAmountToDeposit = expectedAmountToReceivePostRebalanceFrom1 + expectedAmountToReceivePostRebalanceFrom2; + + // args.rebalanceToCallData = _callDataRebalanceToOneVaultxChain(totalAmountToDeposit, args.interimAsset); + // } + function _buildInitiateXChainRebalanceArgs( uint64 REBALANCE_FROM, uint64 REBALANCE_TO, From 7885dfce6329becb36df5d2334a55b58ead6d343 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:57:18 +0200 Subject: [PATCH 21/44] chore: add test_rebalanceSinglePosition_singleXChainSingleVaultDepositSelector() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 088318f29..068c0e12c 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -558,7 +558,21 @@ contract SuperformRouterPlusTest is ProtocolActions { assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); } - + function test_rebalanceSinglePosition_singleXChainSingleVaultDepositSelector() public { + vm.startPrank(deployer); + + _directDeposit(superformId1); + + ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = + _buildRebalanceSinglePositionToOneVaultArgs(deployer); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); + + assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + } // Deposit into multiple vaults on one chain with tokens from another chain. function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { From 55422db6eacc07ae6876122c33c203f8037f2d0a Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:45:47 +0200 Subject: [PATCH 22/44] chore: add _buildRebalanceMultiMultiDstSingleVaultArgs() --- .../router-plus/SuperformRouterPlus.t.sol | 183 +++++++++++++++++- 1 file changed, 182 insertions(+), 1 deletion(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 068c0e12c..04a92191b 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -594,7 +594,40 @@ contract SuperformRouterPlusTest is ProtocolActions { } // Deposit into a single vault on multiple different chains with tokens from any chain. - function test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() public { } + function test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() public { + vm.startPrank(deployer); + + uint64 REBALANCE_FROM_1 = ETH; + uint64 REBALANCE_FROM_2 = OP; + uint64 REBALANCE_TO = ARBI; + + address interimToken = getContract(SOURCE_CHAIN, "DAI"); + + _xChainDeposit(superformId1, REBALANCE_FROM_1, 1); + _xChainDeposit(superformId2, REBALANCE_FROM_2, 1); + + // _directDeposit(superformId1); + // _directDeposit(superformId2); + + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = + _buildRebalanceMultiMultiDstSingleVaultArgs( + interimToken, + superformIds, + REBALANCE_FROM_1, + REBALANCE_FROM_2, + REBALANCE_TO + ); + // args.callData = _callDataRebalanceFromMultiDst(args.interimAsset, args.ids, REBALANCE_FROM_1, REBALANCE_FROM_2); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + vm.stopPrank(); + + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); + + assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + } function test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector() public { // //vm.startPrank(deployer); @@ -3624,6 +3657,154 @@ contract SuperformRouterPlusTest is ProtocolActions { ); } + function _buildRebalanceMultiMultiDstSingleVaultArgs( + address interimToken, + uint256[] calldata superformIds, + uint64 rebalanceFromChainId1, + uint64 rebalanceFromChainId2, + uint64 rebalanceToChainId + ) + internal + returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs args) + { + uint256 initialFork = vm.activeFork(); + + SingleVaultSFData memory singleVaultData1 = new SingleVaultSFData; + SingleVaultSFData memory singleVaultData2 = new SingleVaultSFData; + + vm.selectFork(FORKS[rebalanceFromChainId1]); + + (address superform1,,) = superformIds[0].getSuperform(); + address underlyingToken1 = IBaseForm(superform1).getVaultAsset(); + + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( + 1, + underlyingToken1, + underlyingToken1, + interimToken, + superform1, // from, which address should this be? + rebalanceFromChainId1, + rebalanceToChainId, + rebalanceToChainId, + false, + getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), + uint256(rebalanceToChainId), // liqBridgeToChainId + 1e18, // This should be updated with the actual amount if available + false, + 100, // slippage + 1, + 1, + 1, + address(0) + ); + + singleVaultData1 = SingleVaultSFData({ + superformIds: superformIds[0], + amounts: 1e18, + outputAmounts: 1e18, + maxSlippages: 100, + liqRequests: LiqRequest( + _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), interimToken, address(0), 1, rebalanceToChainId, 0 + ), + permit2data: "", + hasDstSwaps: false, + retain4626s: false, + receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, // deployer? + receiverAddressSP: deployer, + extraFormData: "" + }); + + vm.selectFork(FORKS[rebalanceFromChainId1]); + + (address superform2,,) = superformIds[0].getSuperform(); + address underlyingToken2 = IBaseForm(superform2).getVaultAsset(); + + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( + 1, + underlyingToken2, + underlyingToken2, + interimToken, + superform2, // from, which address should this be? + rebalanceFromChainId2, + rebalanceToChainId, + rebalanceToChainId, + false, + getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), + uint256(rebalanceToChainId), // liqBridgeToChainId + 1e18, // This should be updated with the actual amount if available + false, + 100, // slippage + 1, + 1, + 1, + address(0) + ); + + singleVaultData1 = SingleVaultSFData({ + superformIds: superformIds[1], + amounts: 1e18, + outputAmounts: 1e18, + maxSlippages: 100, + liqRequests: LiqRequest( + _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), interimToken, address(0), 1, rebalanceToChainId, 0 + ), + permit2data: "", + hasDstSwaps: false, + retain4626s: false, + receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, // deployer? + receiverAddressSP: deployer, + extraFormData: "" + }); + + // Set ambIds to AMBs for both origins + uint8[][] memory ambIds = new uint8[][](2); + ambIds[0] = AMBs; + ambIds[1] = AMBs; + + uint64[] memory chainIds = new uint64[](2); + chainIds[0] = rebalanceFromChainId1; + chainIds[1] = rebalanceFromChainId2; + + SingleVaultSFData[] memory singleVaultData = new SingleVaultSFData[](2); + singleVaultData[0] = singleVaultData1; + singleVaultData[1] = singleVaultData2; + + MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq = MultiDstSingleVaultStateReq(ambIds, chainIds, singleVaultData); + + uint256[] memory sharesToRedeem = new uint256[](2); + sharesToRedeem[0] = 1e18; + sharesToRedeem[1] = 1e18; + + // callData = abi.encodeCall( + // IBaseRouter.multiDstSingleVaultDeposit, MultiDstSingleVaultStateReq (ambIds, rebalanceFromChainId1, singleVaultData1) + // ); + + bytes memory callData = _callDataRebalanceFromMultiDst( + interimToken, + superformIds, + rebalanceFromChainId1, + rebalanceFromChainId2 + ); + + bytes memory rebalanceToCallData = abi.encodeCall( + IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq + ); + + args = + ISuperformRouterPlus.RebalanceMultiPositionSyncArgs( + superformIds, + sharesToRedeem, + 1e18, + 2 ether, // 1 ether from each superform ? + 1 ether, + interimToken, + 100, + deployer, + callData, + singleVaultData + ); + } + function _callDataRebalanceFrom(address interimToken) internal view returns (bytes memory) { LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( 1, From 71b836aa6aa5d5ca84f23cc767a03141d462234d Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:47:23 +0200 Subject: [PATCH 23/44] fix: update superformIds in test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 04a92191b..9c1780802 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -609,6 +609,10 @@ contract SuperformRouterPlusTest is ProtocolActions { // _directDeposit(superformId1); // _directDeposit(superformId2); + uint256[] memory superformIds = new uint256[](2); + superformIds[0] = superformId1; + superformIds[1] = superformId2; + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = _buildRebalanceMultiMultiDstSingleVaultArgs( interimToken, From 751d71cbdff702893309b838d556d408dfcce9d1 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:47:46 +0200 Subject: [PATCH 24/44] fix: update return storage location _buildRebalanceMultiMultiDstSingleVaultArgs() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 9c1780802..57fd032c6 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -3669,7 +3669,7 @@ contract SuperformRouterPlusTest is ProtocolActions { uint64 rebalanceToChainId ) internal - returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs args) + returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args) { uint256 initialFork = vm.activeFork(); From 7be0cc81cf7e4796510bc269e3bd543dc09c2ec3 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:52:10 +0200 Subject: [PATCH 25/44] fix: update _buildRebalanceMultiMultiDstSingleVaultArgs() --- .../router-plus/SuperformRouterPlus.t.sol | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 57fd032c6..f408cbd26 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -3673,8 +3673,8 @@ contract SuperformRouterPlusTest is ProtocolActions { { uint256 initialFork = vm.activeFork(); - SingleVaultSFData memory singleVaultData1 = new SingleVaultSFData; - SingleVaultSFData memory singleVaultData2 = new SingleVaultSFData; + SingleVaultSFData memory singleVaultData1; + SingleVaultSFData memory singleVaultData2; vm.selectFork(FORKS[rebalanceFromChainId1]); @@ -3703,16 +3703,16 @@ contract SuperformRouterPlusTest is ProtocolActions { ); singleVaultData1 = SingleVaultSFData({ - superformIds: superformIds[0], - amounts: 1e18, - outputAmounts: 1e18, - maxSlippages: 100, - liqRequests: LiqRequest( + superformId: superformIds[0], + amount: 1e18, + outputAmount: 1e18, + maxSlippage: 100, + liqRequest: LiqRequest( _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), interimToken, address(0), 1, rebalanceToChainId, 0 ), permit2data: "", - hasDstSwaps: false, - retain4626s: false, + hasDstSwap: false, + retain4626: false, receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, // deployer? receiverAddressSP: deployer, extraFormData: "" @@ -3723,7 +3723,7 @@ contract SuperformRouterPlusTest is ProtocolActions { (address superform2,,) = superformIds[0].getSuperform(); address underlyingToken2 = IBaseForm(superform2).getVaultAsset(); - LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs2 = LiqBridgeTxDataArgs( 1, underlyingToken2, underlyingToken2, @@ -3745,16 +3745,16 @@ contract SuperformRouterPlusTest is ProtocolActions { ); singleVaultData1 = SingleVaultSFData({ - superformIds: superformIds[1], - amounts: 1e18, - outputAmounts: 1e18, - maxSlippages: 100, - liqRequests: LiqRequest( - _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), interimToken, address(0), 1, rebalanceToChainId, 0 + superformId: superformIds[1], + amount: 1e18, + outputAmount: 1e18, + maxSlippage: 100, + liqRequest: LiqRequest( + _buildLiqBridgeTxData(liqBridgeTxDataArgs2, false), interimToken, address(0), 1, rebalanceToChainId, 0 ), permit2data: "", - hasDstSwaps: false, - retain4626s: false, + hasDstSwap: false, + retain4626: false, receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, // deployer? receiverAddressSP: deployer, extraFormData: "" @@ -3795,7 +3795,7 @@ contract SuperformRouterPlusTest is ProtocolActions { ); args = - ISuperformRouterPlus.RebalanceMultiPositionSyncArgs( + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( superformIds, sharesToRedeem, 1e18, From e1f91fc0ebb8ebdbca1dfd7190aa0b0feccdaef2 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 11:53:28 +0200 Subject: [PATCH 26/44] fix: update _buildRebalanceMultiMultiDstSingleVaultArgs() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index f408cbd26..b7a5ef3d4 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -3805,7 +3805,7 @@ contract SuperformRouterPlusTest is ProtocolActions { 100, deployer, callData, - singleVaultData + rebalanceToCallData ); } From 79fe34d3578095779a0e8089028138215b1ea1c5 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:20:59 +0200 Subject: [PATCH 27/44] refactor: split _buildRebalanceMultiMultiDstSingleVaultArgs() into helpers --- .../router-plus/SuperformRouterPlus.t.sol | 166 ++++++++---------- 1 file changed, 71 insertions(+), 95 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index b7a5ef3d4..0633fefaf 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -599,7 +599,7 @@ contract SuperformRouterPlusTest is ProtocolActions { uint64 REBALANCE_FROM_1 = ETH; uint64 REBALANCE_FROM_2 = OP; - uint64 REBALANCE_TO = ARBI; + //uint64 REBALANCE_TO = ARBI; address interimToken = getContract(SOURCE_CHAIN, "DAI"); @@ -615,17 +615,17 @@ contract SuperformRouterPlusTest is ProtocolActions { ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = _buildRebalanceMultiMultiDstSingleVaultArgs( - interimToken, superformIds, REBALANCE_FROM_1, REBALANCE_FROM_2, - REBALANCE_TO + ARBI ); // args.callData = _callDataRebalanceFromMultiDst(args.interimAsset, args.ids, REBALANCE_FROM_1, REBALANCE_FROM_2); - SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); - SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); vm.stopPrank(); assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); @@ -3662,8 +3662,7 @@ contract SuperformRouterPlusTest is ProtocolActions { } function _buildRebalanceMultiMultiDstSingleVaultArgs( - address interimToken, - uint256[] calldata superformIds, + uint256[] memory superformIds, uint64 rebalanceFromChainId1, uint64 rebalanceFromChainId2, uint64 rebalanceToChainId @@ -3671,94 +3670,28 @@ contract SuperformRouterPlusTest is ProtocolActions { internal returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args) { - uint256 initialFork = vm.activeFork(); + //uint256 initialFork = vm.activeFork(); + + address interimToken = getContract(SOURCE_CHAIN, "DAI"); SingleVaultSFData memory singleVaultData1; SingleVaultSFData memory singleVaultData2; - vm.selectFork(FORKS[rebalanceFromChainId1]); + //vm.selectFork(FORKS[rebalanceFromChainId1]); (address superform1,,) = superformIds[0].getSuperform(); - address underlyingToken1 = IBaseForm(superform1).getVaultAsset(); - LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( - 1, - underlyingToken1, - underlyingToken1, - interimToken, - superform1, // from, which address should this be? - rebalanceFromChainId1, - rebalanceToChainId, - rebalanceToChainId, - false, - getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), - uint256(rebalanceToChainId), // liqBridgeToChainId - 1e18, // This should be updated with the actual amount if available - false, - 100, // slippage - 1, - 1, - 1, - address(0) - ); + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = _buildLiqBridgeTxDataArgs(interimToken, superform1, rebalanceFromChainId1); - singleVaultData1 = SingleVaultSFData({ - superformId: superformIds[0], - amount: 1e18, - outputAmount: 1e18, - maxSlippage: 100, - liqRequest: LiqRequest( - _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), interimToken, address(0), 1, rebalanceToChainId, 0 - ), - permit2data: "", - hasDstSwap: false, - retain4626: false, - receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, // deployer? - receiverAddressSP: deployer, - extraFormData: "" - }); + singleVaultData1 = _buildSingleVaultSFData(liqBridgeTxDataArgs, superformIds[0], rebalanceFromChainId1); - vm.selectFork(FORKS[rebalanceFromChainId1]); + //vm.selectFork(FORKS[rebalanceFromChainId1]); (address superform2,,) = superformIds[0].getSuperform(); - address underlyingToken2 = IBaseForm(superform2).getVaultAsset(); - LiqBridgeTxDataArgs memory liqBridgeTxDataArgs2 = LiqBridgeTxDataArgs( - 1, - underlyingToken2, - underlyingToken2, - interimToken, - superform2, // from, which address should this be? - rebalanceFromChainId2, - rebalanceToChainId, - rebalanceToChainId, - false, - getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), - uint256(rebalanceToChainId), // liqBridgeToChainId - 1e18, // This should be updated with the actual amount if available - false, - 100, // slippage - 1, - 1, - 1, - address(0) - ); + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs2 = _buildLiqBridgeTxDataArgs(interimToken, superform2, rebalanceFromChainId2); - singleVaultData1 = SingleVaultSFData({ - superformId: superformIds[1], - amount: 1e18, - outputAmount: 1e18, - maxSlippage: 100, - liqRequest: LiqRequest( - _buildLiqBridgeTxData(liqBridgeTxDataArgs2, false), interimToken, address(0), 1, rebalanceToChainId, 0 - ), - permit2data: "", - hasDstSwap: false, - retain4626: false, - receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, // deployer? - receiverAddressSP: deployer, - extraFormData: "" - }); + singleVaultData2 = _buildSingleVaultSFData(liqBridgeTxDataArgs2, superformIds[1], rebalanceFromChainId2); // Set ambIds to AMBs for both origins uint8[][] memory ambIds = new uint8[][](2); @@ -3783,17 +3716,6 @@ contract SuperformRouterPlusTest is ProtocolActions { // IBaseRouter.multiDstSingleVaultDeposit, MultiDstSingleVaultStateReq (ambIds, rebalanceFromChainId1, singleVaultData1) // ); - bytes memory callData = _callDataRebalanceFromMultiDst( - interimToken, - superformIds, - rebalanceFromChainId1, - rebalanceFromChainId2 - ); - - bytes memory rebalanceToCallData = abi.encodeCall( - IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq - ); - args = ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( superformIds, @@ -3804,11 +3726,65 @@ contract SuperformRouterPlusTest is ProtocolActions { interimToken, 100, deployer, - callData, - rebalanceToCallData + _callDataRebalanceFromMultiDst( + interimToken, + superformIds, + rebalanceFromChainId1, + rebalanceFromChainId2 + ), + abi.encodeCall( + IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq + ) ); } + function _buildLiqBridgeTxDataArgs(address interimToken, address superform, uint64 rebalanceFromChainId) internal view returns (LiqBridgeTxDataArgs memory) { + address underlyingToken = IBaseForm(superform2).getVaultAsset(); + + return LiqBridgeTxDataArgs( + 1, + underlyingToken, + underlyingToken, + getContract(SOURCE_CHAIN, "DAI"), + superform2, // from, which address should this be? + rebalanceFromChainId, + ARBI, + ARBI, + false, + getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), + uint256(ARBI), // liqBridgeToChainId + 1e18, // This should be updated with the actual amount if available + false, + 100, // slippage + 1, + 1, + 1, + address(0) + ); + } + + function _buildSingleVaultSFData( + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs, + uint256 superformId, + uint64 rebalanceFromChainId) internal view returns (SingleVaultSFData memory) { + return SingleVaultSFData( + superformId, + 1e18, + 1e18, + 100, + LiqRequest( + _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), getContract(SOURCE_CHAIN, "DAI"), address(0), 1, ARBI, 0 + ), + "", + false, + false, + ROUTER_PLUS_ASYNC_SOURCE, // deployer? + deployer, + "" + ); + } + + function _callDataRebalanceFrom(address interimToken) internal view returns (bytes memory) { LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( 1, From 4c7908163fd694e5770a280918696ea8b8f7e4ba Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:24:03 +0200 Subject: [PATCH 28/44] add _buildRebalanceMultiMultiDstSingleVaultArgs() --- .../router-plus/SuperformRouterPlus.t.sol | 50 ++++++++++++------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 0633fefaf..ca82f33de 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -3717,25 +3717,7 @@ contract SuperformRouterPlusTest is ProtocolActions { // ); args = - ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( - superformIds, - sharesToRedeem, - 1e18, - 2 ether, // 1 ether from each superform ? - 1 ether, - interimToken, - 100, - deployer, - _callDataRebalanceFromMultiDst( - interimToken, - superformIds, - rebalanceFromChainId1, - rebalanceFromChainId2 - ), - abi.encodeCall( - IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq - ) - ); + ; } function _buildLiqBridgeTxDataArgs(address interimToken, address superform, uint64 rebalanceFromChainId) internal view returns (LiqBridgeTxDataArgs memory) { @@ -3784,6 +3766,36 @@ contract SuperformRouterPlusTest is ProtocolActions { ); } + function _buildRebalanceMultiMultiDstSingleVaultArgs(uint64 rebalanceFromChainId1, uint64 rebalanceFromChainId2) internal view returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory) { + uint256[] memory superformIds = new uint256[](2); + superformIds[0] = superformId1; + superformIds[1] = superformId2; + + uint256[] memory sharesToRedeem = new uint256[](2); + sharesToRedeem[0] = 1e18; + sharesToRedeem[1] = 1e18; + + return ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( + superformIds, + sharesToRedeem, + 1e18, + 2 ether, // 1 ether from each superform ? + 1 ether, + interimToken, + 100, + deployer, + _callDataRebalanceFromMultiDst( + getContract(SOURCE_CHAIN, "DAI"), + superformIds, + rebalanceFromChainId1, + rebalanceFromChainId2 + ), + abi.encodeCall( + IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq + ) + ); + } + function _callDataRebalanceFrom(address interimToken) internal view returns (bytes memory) { LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( From c8a3e8ac488af53dafd93917410b8072f41cbe8c Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:33:44 +0200 Subject: [PATCH 29/44] fix: update _buildRebalanceMultiMultiDstSingleVaultArgs() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index ca82f33de..c6753254d 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -3708,16 +3708,11 @@ contract SuperformRouterPlusTest is ProtocolActions { MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq = MultiDstSingleVaultStateReq(ambIds, chainIds, singleVaultData); - uint256[] memory sharesToRedeem = new uint256[](2); - sharesToRedeem[0] = 1e18; - sharesToRedeem[1] = 1e18; - // callData = abi.encodeCall( // IBaseRouter.multiDstSingleVaultDeposit, MultiDstSingleVaultStateReq (ambIds, rebalanceFromChainId1, singleVaultData1) // ); - args = - ; + args = _buildRebalanceMultiMultiDstSingleVaultArgs( rebalanceFromChainId1, rebalanceFromChainId2, multiDstSingleVaultStateReq); } function _buildLiqBridgeTxDataArgs(address interimToken, address superform, uint64 rebalanceFromChainId) internal view returns (LiqBridgeTxDataArgs memory) { @@ -3748,7 +3743,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function _buildSingleVaultSFData( LiqBridgeTxDataArgs memory liqBridgeTxDataArgs, uint256 superformId, - uint64 rebalanceFromChainId) internal view returns (SingleVaultSFData memory) { + uint64 rebalanceFromChainId) internal returns (SingleVaultSFData memory) { return SingleVaultSFData( superformId, 1e18, @@ -3766,7 +3761,7 @@ contract SuperformRouterPlusTest is ProtocolActions { ); } - function _buildRebalanceMultiMultiDstSingleVaultArgs(uint64 rebalanceFromChainId1, uint64 rebalanceFromChainId2) internal view returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory) { + function _buildRebalanceMultiMultiDstSingleVaultArgs(uint64 rebalanceFromChainId1, uint64 rebalanceFromChainId2, MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq) internal returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory) { uint256[] memory superformIds = new uint256[](2); superformIds[0] = superformId1; superformIds[1] = superformId2; @@ -3781,7 +3776,7 @@ contract SuperformRouterPlusTest is ProtocolActions { 1e18, 2 ether, // 1 ether from each superform ? 1 ether, - interimToken, + getContract(SOURCE_CHAIN, "DAI"), 100, deployer, _callDataRebalanceFromMultiDst( @@ -3792,7 +3787,7 @@ contract SuperformRouterPlusTest is ProtocolActions { ), abi.encodeCall( IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq - ) + ) ); } From fa32bf5e9f783f0e7b1584d7dd47565bbc690bbb Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:34:39 +0200 Subject: [PATCH 30/44] fix: update _xChainDeposit() calls in test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index c6753254d..0864c5f20 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -601,10 +601,8 @@ contract SuperformRouterPlusTest is ProtocolActions { uint64 REBALANCE_FROM_2 = OP; //uint64 REBALANCE_TO = ARBI; - address interimToken = getContract(SOURCE_CHAIN, "DAI"); - - _xChainDeposit(superformId1, REBALANCE_FROM_1, 1); - _xChainDeposit(superformId2, REBALANCE_FROM_2, 1); + _xChainDeposit(SOURCE_CHAIN, REBALANCE_FROM_1, 1); + _xChainDeposit(SOURCE_CHAIN, REBALANCE_FROM_2, 1); // _directDeposit(superformId1); // _directDeposit(superformId2); From a7754567c4686e47d9ed4ec53259a090c31c558b Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:36:16 +0200 Subject: [PATCH 31/44] fix: update params in _buildSingleVaultSFData() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 0864c5f20..4f0dcc4c1 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -3681,7 +3681,7 @@ contract SuperformRouterPlusTest is ProtocolActions { LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = _buildLiqBridgeTxDataArgs(interimToken, superform1, rebalanceFromChainId1); - singleVaultData1 = _buildSingleVaultSFData(liqBridgeTxDataArgs, superformIds[0], rebalanceFromChainId1); + singleVaultData1 = _buildSingleVaultSFData(liqBridgeTxDataArgs, superformIds[0]); //vm.selectFork(FORKS[rebalanceFromChainId1]); @@ -3689,7 +3689,7 @@ contract SuperformRouterPlusTest is ProtocolActions { LiqBridgeTxDataArgs memory liqBridgeTxDataArgs2 = _buildLiqBridgeTxDataArgs(interimToken, superform2, rebalanceFromChainId2); - singleVaultData2 = _buildSingleVaultSFData(liqBridgeTxDataArgs2, superformIds[1], rebalanceFromChainId2); + singleVaultData2 = _buildSingleVaultSFData(liqBridgeTxDataArgs2, superformIds[1]); // Set ambIds to AMBs for both origins uint8[][] memory ambIds = new uint8[][](2); @@ -3740,8 +3740,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function _buildSingleVaultSFData( LiqBridgeTxDataArgs memory liqBridgeTxDataArgs, - uint256 superformId, - uint64 rebalanceFromChainId) internal returns (SingleVaultSFData memory) { + uint256 superformId) internal returns (SingleVaultSFData memory) { return SingleVaultSFData( superformId, 1e18, From ca0e56350a8f1c8df65262b1c25da5b3913c9307 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:39:41 +0200 Subject: [PATCH 32/44] update REBALANCE_TO chainId in test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 4f0dcc4c1..a820ec4a3 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -601,8 +601,8 @@ contract SuperformRouterPlusTest is ProtocolActions { uint64 REBALANCE_FROM_2 = OP; //uint64 REBALANCE_TO = ARBI; - _xChainDeposit(SOURCE_CHAIN, REBALANCE_FROM_1, 1); - _xChainDeposit(SOURCE_CHAIN, REBALANCE_FROM_2, 1); + _xChainDeposit(superformId5ETH, REBALANCE_FROM_1, 1); + _xChainDeposit(superformId5ETH, REBALANCE_FROM_2, 1); // _directDeposit(superformId1); // _directDeposit(superformId2); @@ -3723,11 +3723,11 @@ contract SuperformRouterPlusTest is ProtocolActions { getContract(SOURCE_CHAIN, "DAI"), superform2, // from, which address should this be? rebalanceFromChainId, - ARBI, - ARBI, + ETH, + ETH, false, getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), - uint256(ARBI), // liqBridgeToChainId + uint256(ETH), // liqBridgeToChainId 1e18, // This should be updated with the actual amount if available false, 100, // slippage @@ -3747,7 +3747,7 @@ contract SuperformRouterPlusTest is ProtocolActions { 1e18, 100, LiqRequest( - _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), getContract(SOURCE_CHAIN, "DAI"), address(0), 1, ARBI, 0 + _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), getContract(SOURCE_CHAIN, "DAI"), address(0), 1, ETH, 0 ), "", false, From 8e2c0b73918ef44f6bc40a92350fe76270c418e6 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:40:37 +0200 Subject: [PATCH 33/44] fix: update REBALANCE_TO chainId in test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index a820ec4a3..3b0ad3a5d 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -616,7 +616,7 @@ contract SuperformRouterPlusTest is ProtocolActions { superformIds, REBALANCE_FROM_1, REBALANCE_FROM_2, - ARBI + ETH ); // args.callData = _callDataRebalanceFromMultiDst(args.interimAsset, args.ids, REBALANCE_FROM_1, REBALANCE_FROM_2); From 2d7208aa2f6b8594ea6cc1df6b55776114b734f7 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:43:37 +0200 Subject: [PATCH 34/44] fix: update fork in test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() --- test/unit/router-plus/SuperformRouterPlus.t.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 3b0ad3a5d..0565eef69 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -601,6 +601,8 @@ contract SuperformRouterPlusTest is ProtocolActions { uint64 REBALANCE_FROM_2 = OP; //uint64 REBALANCE_TO = ARBI; + vm.selectFork(FORKS[SOURCE_CHAIN]); + _xChainDeposit(superformId5ETH, REBALANCE_FROM_1, 1); _xChainDeposit(superformId5ETH, REBALANCE_FROM_2, 1); From 9e60021c04d17c99b3dfcc326da98dfbb467b7b2 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:12:38 +0200 Subject: [PATCH 35/44] fix: rm unused helper functions --- .../router-plus/SuperformRouterPlus.t.sol | 153 +++++------------- 1 file changed, 36 insertions(+), 117 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 0565eef69..9b97e763b 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -9,6 +9,7 @@ import { IBaseSuperformRouterPlus } from "src/interfaces/IBaseSuperformRouterPlu import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import { MultiVaultSFData } from "src/types/DataTypes.sol"; +import "forge-std/console2.sol"; contract RejectEther { // This function will revert when called, simulating a contract that can't receive native tokens @@ -594,33 +595,50 @@ contract SuperformRouterPlusTest is ProtocolActions { } // Deposit into a single vault on multiple different chains with tokens from any chain. - function test_rebalanceSinglePosition_multiDstSingleVaultDepositSelector() public { - vm.startPrank(deployer); - - uint64 REBALANCE_FROM_1 = ETH; - uint64 REBALANCE_FROM_2 = OP; - //uint64 REBALANCE_TO = ARBI; - - vm.selectFork(FORKS[SOURCE_CHAIN]); + function test_rebalanceMultiPositions_multiDstSingleVaultDepositSelector() public { - _xChainDeposit(superformId5ETH, REBALANCE_FROM_1, 1); - _xChainDeposit(superformId5ETH, REBALANCE_FROM_2, 1); + deal(getContract(SOURCE_CHAIN, "DAI"), deployer, 100e18); - // _directDeposit(superformId1); - // _directDeposit(superformId2); + vm.startPrank(deployer); + _directDeposit(superformId1); + _directDeposit(superformId2); + vm.stopPrank(); uint256[] memory superformIds = new uint256[](2); superformIds[0] = superformId1; superformIds[1] = superformId2; + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1e18; + amounts[1] = 1e18; + + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = 1e18; + outputAmounts[1] = 1e18; + + uint256[] memory maxSlippages = new uint256[](2); + maxSlippages[0] = 100; + maxSlippages[1] = 100; + + MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq = MultiDstSingleVaultStateReq({ + superformIds: superformIds, + amounts: amounts, + outputAmounts: outputAmounts, + maxSlippages: maxSlippages, + }); + + uint256[] memory sharesToRedeem = new uint256[](2); + sharesToRedeem[0] = 1e18; + sharesToRedeem[1] = 1e18; + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = - _buildRebalanceMultiMultiDstSingleVaultArgs( + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( superformIds, - REBALANCE_FROM_1, - REBALANCE_FROM_2, - ETH - ); - // args.callData = _callDataRebalanceFromMultiDst(args.interimAsset, args.ids, REBALANCE_FROM_1, REBALANCE_FROM_2); + sharesToRedeem, + 1e18, + maxSlippages, + multiDstSingleVaultStateReq + ); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); @@ -3661,105 +3679,6 @@ contract SuperformRouterPlusTest is ProtocolActions { ); } - function _buildRebalanceMultiMultiDstSingleVaultArgs( - uint256[] memory superformIds, - uint64 rebalanceFromChainId1, - uint64 rebalanceFromChainId2, - uint64 rebalanceToChainId - ) - internal - returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args) - { - //uint256 initialFork = vm.activeFork(); - - address interimToken = getContract(SOURCE_CHAIN, "DAI"); - - SingleVaultSFData memory singleVaultData1; - SingleVaultSFData memory singleVaultData2; - - //vm.selectFork(FORKS[rebalanceFromChainId1]); - - (address superform1,,) = superformIds[0].getSuperform(); - - LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = _buildLiqBridgeTxDataArgs(interimToken, superform1, rebalanceFromChainId1); - - singleVaultData1 = _buildSingleVaultSFData(liqBridgeTxDataArgs, superformIds[0]); - - //vm.selectFork(FORKS[rebalanceFromChainId1]); - - (address superform2,,) = superformIds[0].getSuperform(); - - LiqBridgeTxDataArgs memory liqBridgeTxDataArgs2 = _buildLiqBridgeTxDataArgs(interimToken, superform2, rebalanceFromChainId2); - - singleVaultData2 = _buildSingleVaultSFData(liqBridgeTxDataArgs2, superformIds[1]); - - // Set ambIds to AMBs for both origins - uint8[][] memory ambIds = new uint8[][](2); - ambIds[0] = AMBs; - ambIds[1] = AMBs; - - uint64[] memory chainIds = new uint64[](2); - chainIds[0] = rebalanceFromChainId1; - chainIds[1] = rebalanceFromChainId2; - - SingleVaultSFData[] memory singleVaultData = new SingleVaultSFData[](2); - singleVaultData[0] = singleVaultData1; - singleVaultData[1] = singleVaultData2; - - MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq = MultiDstSingleVaultStateReq(ambIds, chainIds, singleVaultData); - - // callData = abi.encodeCall( - // IBaseRouter.multiDstSingleVaultDeposit, MultiDstSingleVaultStateReq (ambIds, rebalanceFromChainId1, singleVaultData1) - // ); - - args = _buildRebalanceMultiMultiDstSingleVaultArgs( rebalanceFromChainId1, rebalanceFromChainId2, multiDstSingleVaultStateReq); - } - - function _buildLiqBridgeTxDataArgs(address interimToken, address superform, uint64 rebalanceFromChainId) internal view returns (LiqBridgeTxDataArgs memory) { - address underlyingToken = IBaseForm(superform2).getVaultAsset(); - - return LiqBridgeTxDataArgs( - 1, - underlyingToken, - underlyingToken, - getContract(SOURCE_CHAIN, "DAI"), - superform2, // from, which address should this be? - rebalanceFromChainId, - ETH, - ETH, - false, - getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), - uint256(ETH), // liqBridgeToChainId - 1e18, // This should be updated with the actual amount if available - false, - 100, // slippage - 1, - 1, - 1, - address(0) - ); - } - - function _buildSingleVaultSFData( - LiqBridgeTxDataArgs memory liqBridgeTxDataArgs, - uint256 superformId) internal returns (SingleVaultSFData memory) { - return SingleVaultSFData( - superformId, - 1e18, - 1e18, - 100, - LiqRequest( - _buildLiqBridgeTxData(liqBridgeTxDataArgs, false), getContract(SOURCE_CHAIN, "DAI"), address(0), 1, ETH, 0 - ), - "", - false, - false, - ROUTER_PLUS_ASYNC_SOURCE, // deployer? - deployer, - "" - ); - } - function _buildRebalanceMultiMultiDstSingleVaultArgs(uint64 rebalanceFromChainId1, uint64 rebalanceFromChainId2, MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq) internal returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory) { uint256[] memory superformIds = new uint256[](2); superformIds[0] = superformId1; From 53d46c090787c73da992313b35e7fd8550b4122b Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:14:00 +0200 Subject: [PATCH 36/44] fux: rm _buildRebalanceMultiMultiDstSingleVaultArgs() --- .../router-plus/SuperformRouterPlus.t.sol | 42 ++++--------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 9b97e763b..b5a9f9160 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -636,8 +636,15 @@ contract SuperformRouterPlusTest is ProtocolActions { superformIds, sharesToRedeem, 1e18, - maxSlippages, - multiDstSingleVaultStateReq + 1 ether, + 1 ether, + getContract(SOURCE_CHAIN, "DAI"), + 100, + deployer, + "", + abi.encodeCall( + IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq + ) ); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); @@ -3679,37 +3686,6 @@ contract SuperformRouterPlusTest is ProtocolActions { ); } - function _buildRebalanceMultiMultiDstSingleVaultArgs(uint64 rebalanceFromChainId1, uint64 rebalanceFromChainId2, MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq) internal returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory) { - uint256[] memory superformIds = new uint256[](2); - superformIds[0] = superformId1; - superformIds[1] = superformId2; - - uint256[] memory sharesToRedeem = new uint256[](2); - sharesToRedeem[0] = 1e18; - sharesToRedeem[1] = 1e18; - - return ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( - superformIds, - sharesToRedeem, - 1e18, - 2 ether, // 1 ether from each superform ? - 1 ether, - getContract(SOURCE_CHAIN, "DAI"), - 100, - deployer, - _callDataRebalanceFromMultiDst( - getContract(SOURCE_CHAIN, "DAI"), - superformIds, - rebalanceFromChainId1, - rebalanceFromChainId2 - ), - abi.encodeCall( - IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq - ) - ); - } - - function _callDataRebalanceFrom(address interimToken) internal view returns (bytes memory) { LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( 1, From b613612ea35ab72770daa633639f23ec21f7e32a Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:28:14 +0200 Subject: [PATCH 37/44] fix: update test_rebalanceMultiPositions_multiDstSingleVaultDepositSelector() --- .../router-plus/SuperformRouterPlus.t.sol | 544 +++++++++--------- 1 file changed, 285 insertions(+), 259 deletions(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index b5a9f9160..46a71c688 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -8,7 +8,7 @@ import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAs import { IBaseSuperformRouterPlus } from "src/interfaces/IBaseSuperformRouterPlus.sol"; import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; -import { MultiVaultSFData } from "src/types/DataTypes.sol"; +import { MultiVaultSFData, MultiDstMultiVaultStateReq, SingleXChainMultiVaultStateReq } from "src/types/DataTypes.sol"; import "forge-std/console2.sol"; contract RejectEther { @@ -575,7 +575,6 @@ contract SuperformRouterPlusTest is ProtocolActions { assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } - // Deposit into multiple vaults on one chain with tokens from another chain. function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { vm.startPrank(deployer); @@ -594,9 +593,9 @@ contract SuperformRouterPlusTest is ProtocolActions { assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } - // Deposit into a single vault on multiple different chains with tokens from any chain. function test_rebalanceMultiPositions_multiDstSingleVaultDepositSelector() public { - + vm.activeFork(); + vm.selectFork(FORKS[SOURCE_CHAIN]); deal(getContract(SOURCE_CHAIN, "DAI"), deployer, 100e18); vm.startPrank(deployer); @@ -608,23 +607,97 @@ contract SuperformRouterPlusTest is ProtocolActions { superformIds[0] = superformId1; superformIds[1] = superformId2; - uint256[] memory amounts = new uint256[](2); - amounts[0] = 1e18; - amounts[1] = 1e18; + (address superform1,,) = superformId1.getSuperform(); + (address superform2,,) = superformId2.getSuperform(); - uint256[] memory outputAmounts = new uint256[](2); - outputAmounts[0] = 1e18; - outputAmounts[1] = 1e18; + SingleVaultSFData[] memory superformsData = new SingleVaultSFData[](3); - uint256[] memory maxSlippages = new uint256[](2); - maxSlippages[0] = 100; - maxSlippages[1] = 100; + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs1 = LiqBridgeTxDataArgs( + 1, + getContract(SOURCE_CHAIN, "DAI"), + getContract(SOURCE_CHAIN, "DAI"), + getContract(SOURCE_CHAIN, "DAI"), + superform1, + SOURCE_CHAIN, + SOURCE_CHAIN, + SOURCE_CHAIN, + false, + getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), + uint256(SOURCE_CHAIN), + 1e18, // This should be updated with the actual amount if available + true, + 0, + 1, + 1, + 1, + address(0) + ); + + superformsData[0] = SingleVaultSFData({ + superformId: superformId1, + amount: 1e18, + outputAmount: 1e18, + maxSlippage: 100, + liqRequest: LiqRequest( + _buildLiqBridgeTxData(liqBridgeTxDataArgs1, false), getContract(SOURCE_CHAIN, "DAI"), address(0), 1, SOURCE_CHAIN, 0 + ), + permit2data: "", + hasDstSwap: false, + retain4626: false, + receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, + receiverAddressSP: deployer, + extraFormData: "" + }); + + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs2 = LiqBridgeTxDataArgs( + 1, + getContract(SOURCE_CHAIN, "DAI"), + getContract(SOURCE_CHAIN, "DAI"), + getContract(SOURCE_CHAIN, "DAI"), + superform2, + SOURCE_CHAIN, + SOURCE_CHAIN, + SOURCE_CHAIN, + false, + getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), + uint256(SOURCE_CHAIN), + 1e18, // This should be updated with the actual amount if available + true, + 0, + 1, + 1, + 1, + address(0) + ); + + superformsData[1] = SingleVaultSFData({ + superformId: superformId2, + amount: 1e18, + outputAmount: 1e18, + maxSlippage: 100, + liqRequest: LiqRequest( + _buildLiqBridgeTxData(liqBridgeTxDataArgs2, false), getContract(SOURCE_CHAIN, "DAI"), address(0), 1, SOURCE_CHAIN, 0 + ), + permit2data: "", + hasDstSwap: false, + retain4626: false, + receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, + receiverAddressSP: deployer, + extraFormData: "" + }); + + uint8[][] memory ambIds = new uint8[][](2); + ambIds[0] = AMBs; + ambIds[1] = AMBs; + + uint64[] memory dstChainIds = new uint64[](2); + dstChainIds[0] = SOURCE_CHAIN; + dstChainIds[1] = SOURCE_CHAIN; MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq = MultiDstSingleVaultStateReq({ - superformIds: superformIds, - amounts: amounts, - outputAmounts: outputAmounts, - maxSlippages: maxSlippages, + ambIds: ambIds, + dstChainIds: dstChainIds, + superformsData: superformsData }); uint256[] memory sharesToRedeem = new uint256[](2); @@ -641,12 +714,23 @@ contract SuperformRouterPlusTest is ProtocolActions { getContract(SOURCE_CHAIN, "DAI"), 100, deployer, - "", + // abi.encodeCall( + // IBaseRouter.multiDstSingleVaultDeposit, multiDstSingleVaultStateReq + // ), + _callDataRebalanceFromMultiDst( + getContract(SOURCE_CHAIN, "DAI"), + superformIds, + SOURCE_CHAIN, + SOURCE_CHAIN + ), abi.encodeCall( - IBaseRouter.multiDstSingleVaultWithdraw, multiDstSingleVaultStateReq + IBaseRouter.multiDstSingleVaultDeposit, MultiDstSingleVaultStateReq ) - ); + //_buildCallDataRebalanceToSingleVaultFromMultiDst(1e18) + //_callDataRebalanceToSingleVaultFromMultiDst(1e18) + ); + vm.startPrank(deployer); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); @@ -654,271 +738,213 @@ contract SuperformRouterPlusTest is ProtocolActions { vm.stopPrank(); assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); - - assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } - function test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector() public { - // //vm.startPrank(deployer); + function test_rebalanceMultiPositions_multiDstMultiVaultDepositSelector() public { + // vm.activeFork(); // vm.selectFork(FORKS[SOURCE_CHAIN]); + // deal(getContract(SOURCE_CHAIN, "DAI"), deployer, 100e18); - // uint64 REBALANCE_FROM_1 = ETH; - // uint64 REBALANCE_FROM_2 = OP; - // uint64 REBALANCE_TO = OP; - - // deal(getContract(SOURCE_CHAIN, "DAI"), deployer, 10e18); - - // vm.prank(deployer); - // _xChainDeposit(superformId5ETH, REBALANCE_FROM_1, 1); + // vm.startPrank(deployer); + // _directDeposit(superformId1); + // _directDeposit(superformId2); + // vm.stopPrank(); - // vm.prank(deployer); - // _xChainDeposit(superformId6ETH, REBALANCE_FROM_1, 2); + // uint256[] memory superformIds = new uint256[](2); + // superformIds[0] = superformId1; + // superformIds[1] = superformId2; + + // (address superform1,,) = superformId1.getSuperform(); + // (address superform2,,) = superformId2.getSuperform(); + + // MultiVaultSFData[] memory superformsData = new MultiVaultSFData[](2); + + // uint256[] memory superformIds = new uint256[](1); + // superformIds[0] = superformId1; + // superformIds[1] = superformId2; + + // uint256[] memory amounts = new uint256[](1); + // amounts[0] = 1e18; + // amounts[1] = 1e18; + + // uint256[] memory outputAmounts = new uint256[](1); + // outputAmounts[0] = 1e18; + // outputAmounts[1] = 1e18; + + // uint256[] memory maxSlippages = new uint256[](1); + // maxSlippages[0] = 100; + // maxSlippages[1] = 100; + + // LiqRequest memory liqReq1 = LiqRequest( + // _buildLiqBridgeTxData( + // LiqBridgeTxDataArgs( + // 1, + // getContract(SOURCE_CHAIN, "DAI"), + // getContract(SOURCE_CHAIN, "DAI"), + // getContract(SOURCE_CHAIN, "DAI"), + // superform1, + // SOURCE_CHAIN, + // SOURCE_CHAIN, + // SOURCE_CHAIN, + // false, + // getContract(SOURCE_CHAIN, "CoreStateRegistry"), + // uint256(SOURCE_CHAIN), + // 1e18, + // //1e18, + // false, + // /// @dev placeholder value, not used + // 0, + // 1, + // 1, + // 1, + // address(0) + // ), + // false + // ), + // getContract(SOURCE_CHAIN, "DAI"), + // address(0), + // 1, + // SOURCE_CHAIN, + // 0 + // ); + + // LiqRequest memory liqReq2 = LiqRequest( + // _buildLiqBridgeTxData( + // LiqBridgeTxDataArgs( + // 1, + // getContract(SOURCE_CHAIN, "DAI"), + // getContract(SOURCE_CHAIN, "DAI"), + // getContract(SOURCE_CHAIN, "DAI"), + // superform1, + // SOURCE_CHAIN, + // SOURCE_CHAIN, + // SOURCE_CHAIN, + // false, + // getContract(SOURCE_CHAIN, "CoreStateRegistry"), + // uint256(SOURCE_CHAIN), + // 1e18, + // //1e18, + // false, + // /// @dev placeholder value, not used + // 0, + // 1, + // 1, + // 1, + // address(0) + // ), + // false + // ), + // getContract(SOURCE_CHAIN, "DAI"), + // address(0), + // 1, + // SOURCE_CHAIN, + // 0 + // ); + + // LiqRequest[] memory liqRequests = new LiqRequest[](2); + // liqRequests[0] = liqReq1; + // liqRequests[1] = liqReq2; + + // superformsData[0] = MultiVaultSFData({ + // superformId: superformId1, + // amounts: amounts, + // outputAmounts: outputAmounts, + // maxSlippages: maxSlippages, + // liqRequests: liqRequests, + // permit2data: "", + // hasDstSwap: false, + // retain4626: false, + // receiverAddress: deployer, + // receiverAddressSP: deployer, + // extraFormData: "" + // }); - // vm.prank(deployer); - // _xChainDeposit(superformId4OP, REBALANCE_FROM_2, 1); + // uint256[] memory ids2 = new uint256[](2); + // ids2[0] = superformId3; + // ids2[1] = superformId4; - // vm.selectFork(FORKS[SOURCE_CHAIN]); - // ISuperformRouterPlus.InitiateXChainRebalanceMultiArgs memory rebalanceArgs = - // _buildInitiateXChainRebalanceMultiDstToMultiArgs(REBALANCE_FROM_1, REBALANCE_FROM_2, REBALANCE_TO); + // uint256[] memory amounts2 = new uint256[](2); + // amounts2[0] = 1e18; + // amounts2[1] = 1e18; - // vm.prank(deployer); - // SuperPositions(SUPER_POSITIONS_SOURCE).setApprovalForAll(ROUTER_PLUS_SOURCE, true); + // uint256[] memory outputAmounts2 = new uint256[](2); + // outputAmounts2[0] = 1e18; + // outputAmounts2[1] = 1e18; - // // vm.startPrank(deployer); - // // _directDeposit(superformId1); - // // _directDeposit(superformId2); - // // vm.stopPrank(); + // uint256[] memory maxSlippages2 = new uint256[](2); + // maxSlippages2[0] = 100; + // maxSlippages2[1] = 100; - // // Setup: Create two destination superforms on the same chain + // LiqRequest[] memory liqRequests2 = new LiqRequest[](2); + // liqRequests2[0] = liqReq1; // ToDo: check + // liqRequests2[1] = liqReq2; - // MultiVaultSFData memory sfData = MultiVaultSFData({ - // superformIds: new uint256[](2), - // amounts: new uint256[](2), - // outputAmounts: new uint256[](2), - // maxSlippages: new uint256[](2), - // liqRequests: new LiqRequest[](2), + // superformsData[1] = MultiVaultSFData({ + // superformId: superformId3, + // amounts: amounts2, + // outputAmounts: outputAmounts2, + // maxSlippages: maxSlippages2, + // liqRequests: liqRequests2, // permit2data: "", - // hasDstSwaps: new bool[](2), - // retain4626s: new bool[](2), - // receiverAddress: address(deployer), - // receiverAddressSP: address(deployer), + // hasDstSwap: false, + // retain4626: false, + // receiverAddress: deployer, + // receiverAddressSP: deployer, // extraFormData: "" // }); - // sfData.superformIds[0] = superformId1; - // sfData.superformIds[1] = superformId2; - // sfData.amounts[0] = 5e17; // 0.5 ether - // sfData.amounts[1] = 5e17; // 0.5 ether - // sfData.outputAmounts[0] = 5e17; - // sfData.outputAmounts[1] = 5e17; - // sfData.maxSlippages[0] = 100; - // sfData.maxSlippages[1] = 100; - - // MultiVaultSFData[] memory multiVaultSFData = new MultiVaultSFData[](1); - // multiVaultSFData[0] = sfData; - - // address interimAsset = getContract(SOURCE_CHAIN, "DAI"); - - // for (uint256 i = 0; i < 2; i++) { - // sfData.liqRequests[i] = LiqRequest({ - // txData: "", - // token: interimAsset, - // interimToken: address(0), - // bridgeId: 0, - // liqDstChainId: SOURCE_CHAIN, - // nativeAmount: 0 - // }); - // } - - // // IBaseSuperformRouterPlus.XChainRebalanceData memory data = IBaseSuperformRouterPlus.XChainRebalanceData({ - // // rebalanceSelector: IBaseRouter.multiDstMultiVaultDeposit.selector, - // // interimAsset: interimAsset, - // // slippage: 100, - // // expectedAmountInterimAsset: 1e18, - // // rebalanceToAmbIds: new uint8[][](0), - // // rebalanceToDstChainIds: new uint64[](0), - // // rebalanceToSfData: abi.encode(multiVaultSFData) - // // }); - - // // vm.startPrank(ROUTER_PLUS_SOURCE); - // // SuperformRouterPlusAsync(ROUTER_PLUS_ASYNC_SOURCE).setXChainRebalanceCallData(deployer, 1, data); - // // vm.stopPrank(); - - // uint256[][] memory newAmounts = new uint256[][](1); - // newAmounts[0] = new uint256[](2); - // newAmounts[0][0] = 5e17; - // newAmounts[0][1] = 5e17; - - // uint256[][] memory newOutputAmounts = new uint256[][](1); - // newOutputAmounts[0] = new uint256[](2); - // newOutputAmounts[0][0] = 5e17; - // newOutputAmounts[0][1] = 5e17; - - // // LiqRequest[][] memory liqRequests = new LiqRequest[][](0); - - // // ISuperformRouterPlusAsync.CompleteCrossChainRebalanceArgs memory completeArgs = ISuperformRouterPlusAsync - // // .CompleteCrossChainRebalanceArgs({ - // // receiverAddressSP: address(deployer), - // // routerPlusPayloadId: 1, - // // amountReceivedInterimAsset: 1e18, - // // newAmounts: newAmounts, - // // newOutputAmounts: newOutputAmounts, - // // liqRequests: liqRequests - // // }); - - // deal(interimAsset, address(ROUTER_PLUS_ASYNC_SOURCE), 1e18); + // uint8[][] memory ambIds = new uint8[][](2); + // ambIds[0] = AMBs; + // ambIds[1] = AMBs; - // vm.startPrank(deployer); - // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); - // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); + // uint64[] memory dstChainIds = new uint64[](2); + // dstChainIds[0] = SOURCE_CHAIN; + // dstChainIds[1] = SOURCE_CHAIN; + + // MultiDstMultiVaultStateReq memory multiDstSingleVaultStateReq = MultiDstMultiVaultStateReq({ + // ambIds: ambIds, + // dstChainIds: dstChainIds, + // superformsData: superformsData + // }); // uint256[] memory sharesToRedeem = new uint256[](2); // sharesToRedeem[0] = 1e18; // sharesToRedeem[1] = 1e18; - // // uint256[] memory ids = new uint256[](2); - // // ids[0] = superformId1; - // // ids[1] = superformId2; - - // uint8[][] memory ambIds_ = new uint8[][](2); - // ambIds_[0] = new uint8[](2); - // ambIds_[0][0] = AMBs[0]; - // ambIds_[0][1] = AMBs[1]; - // ambIds_[1] = new uint8[](2); - // ambIds_[1][0] = AMBs[0]; - // ambIds_[1][1] = AMBs[1]; - - // uint64[] memory dstChainIds = new uint64[](2); - // dstChainIds[0] = OP; - // dstChainIds[1] = ETH; - - // // MultiVaultSFData[] memory mvSfData = new MultiVaultSFData[](2); - // // mvSfData[0] = MultiVaultSFData({ - // // superformIds: new uint256[](2), - // // amounts: new uint256[](2), - // // outputAmounts: new uint256[](2), - // // maxSlippages: new uint256[](2), - // // liqRequests: new LiqRequest[](2), - // // permit2data: "", - // // hasDstSwaps: new bool[](2), - // // retain4626s: new bool[](2), - // // receiverAddress: address(deployer), - // // receiverAddressSP: address(deployer), - // // extraFormData: "" - // // }); - - // // mvSfData[0].superformIds[0] = superformId1; - // // mvSfData[0].superformIds[1] = superformId2; - // // mvSfData[0].amounts[0] = 1e18; - // // mvSfData[0].amounts[1] = 1e18; - // // mvSfData[0].outputAmounts[0] = 1e18; - // // mvSfData[0].outputAmounts[1] = 1e18; - // // mvSfData[0].maxSlippages[0] = 300; - // // mvSfData[0].maxSlippages[1] = 300; - // // mvSfData[0].liqRequests[0] = LiqRequest({ - // // txData: "", - // // token: address(0), - // // interimToken: address(0), - // // bridgeId: 0, - // // liqDstChainId: 0, - // // nativeAmount: 0 - // // }); - // // mvSfData[0].liqRequests[1] = LiqRequest({ - // // txData: "", - // // token: address(0), - // // interimToken: address(0), - // // bridgeId: 0, - // // liqDstChainId: 0, - // // nativeAmount: 0 - // // }); - // // mvSfData[0].hasDstSwaps[0] = false; - // // mvSfData[0].hasDstSwaps[1] = false; - // // mvSfData[0].retain4626s[0] = false; - // // mvSfData[0].retain4626s[1] = false; - // // mvSfData[0].receiverAddress = address(deployer); - // // mvSfData[0].receiverAddressSP = address(deployer); - // // mvSfData[0].extraFormData = ""; - - // // mvSfData[1] = MultiVaultSFData({ - // // superformIds: new uint256[](2), - // // amounts: new uint256[](2), - // // outputAmounts: new uint256[](2), - // // maxSlippages: new uint256[](2), - // // liqRequests: new LiqRequest[](2), - // // permit2data: "", - // // hasDstSwaps: new bool[](2), - // // retain4626s: new bool[](2), - // // receiverAddress: address(deployer), - // // receiverAddressSP: address(deployer), - // // extraFormData: "" - // // }); - - // // mvSfData[1].superformIds[0] = superformId1; - // // mvSfData[1].superformIds[1] = superformId2; - // // mvSfData[1].amounts[0] = 1e18; - // // mvSfData[1].amounts[1] = 1e18; - // // mvSfData[1].outputAmounts[0] = 1e18; - // // mvSfData[1].outputAmounts[1] = 1e18; - // // mvSfData[1].maxSlippages[0] = 300; - // // mvSfData[1].maxSlippages[1] = 300; - // // mvSfData[1].liqRequests[0] = LiqRequest({ - // // txData: "", - // // token: address(0), - // // interimToken: address(0), - // // bridgeId: 0, - // // liqDstChainId: 0, - // // nativeAmount: 0 - // // }); - // // mvSfData[1].liqRequests[1] = LiqRequest({ - // // txData: "", - // // token: address(0), - // // interimToken: address(0), - // // bridgeId: 0, - // // liqDstChainId: 0, - // // nativeAmount: 0 - // // }); - // // mvSfData[1].hasDstSwaps[0] = false; - // // mvSfData[1].hasDstSwaps[1] = false; - // // mvSfData[1].retain4626s[0] = false; - // // mvSfData[1].retain4626s[1] = false; - // // mvSfData[1].receiverAddress = address(deployer); - // // mvSfData[1].receiverAddressSP = address(deployer); - // // mvSfData[1].extraFormData = ""; - // // vm.stopPrank(); - - // // vm.startPrank(ROUTER_PLUS_SOURCE); - // // IBaseSuperformRouterPlus.XChainRebalanceData memory data = IBaseSuperformRouterPlus.XChainRebalanceData({ - // // rebalanceSelector: IBaseRouter.multiDstMultiVaultDeposit.selector, - // // interimAsset: address(0x678), - // // slippage: 600, - // // expectedAmountInterimAsset: 6e18, - // // rebalanceToAmbIds: ambIds_, - // // rebalanceToDstChainIds: dstChainIds, - // // rebalanceToSfData: abi.encode(mvSfData) - // // }); + // ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = + // ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( + // superformIds, + // sharesToRedeem, + // 1e18, + // 1 ether, + // 1 ether, + // getContract(SOURCE_CHAIN, "DAI"), + // 100, + // deployer, + // // abi.encodeCall( + // // IBaseRouter.multiDstMultiVaultWithdraw, multiDstMultiVaultStateReq + // // ), + // _callDataRebalanceFromMultiDst( + // getContract(SOURCE_CHAIN, "DAI"), + // superformIds, + // SOURCE_CHAIN, + // SOURCE_CHAIN + // ), + // abi.encodeCall( + // IBaseRouter.multiDstMultiVaultDeposit, MultiDstMultiVaultStateReq + // ) + // ); // vm.startPrank(deployer); - // MultiDstMultiVaultStateReq memory req = MultiDstMultiVaultStateReq(ambIds_, dstChainIds, multiVaultSFData); - // ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory positionArgs = ISuperformRouterPlus - // .RebalanceMultiPositionsSyncArgs({ - // ids: sfData.superformIds, - // sharesToRedeem: sharesToRedeem, - // expectedAmountToReceivePostRebalanceFrom: 10_000, - // rebalanceFromMsgValue: 1 ether, - // rebalanceToMsgValue: 1 ether, - // interimAsset: getContract(SOURCE_CHAIN, "DAI"), - // slippage: 300, - // receiverAddressSP: address(deployer), - // callData: _callDataRebalanceFromTwoVaults(getContract(SOURCE_CHAIN, "DAI")), - // rebalanceToCallData: abi.encodeCall(IBaseRouter.multiDstMultiVaultDeposit, req) - // }); - - // SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(positionArgs); + // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); + // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); + + // SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); // vm.stopPrank(); // assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); - - // assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + // assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } function test_refundUnusedAndResetApprovals_failedToSendNative() public { From 61a12ab683db88c634fe2adc8ac7a5778eaa6c25 Mon Sep 17 00:00:00 2001 From: Tamara Ringas <69479754+TamaraRingas@users.noreply.github.com> Date: Tue, 29 Oct 2024 12:28:54 +0200 Subject: [PATCH 38/44] import MultiDstSingleVaultStateReq --- test/unit/router-plus/SuperformRouterPlus.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 46a71c688..66c3edb6a 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -8,7 +8,7 @@ import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAs import { IBaseSuperformRouterPlus } from "src/interfaces/IBaseSuperformRouterPlus.sol"; import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; -import { MultiVaultSFData, MultiDstMultiVaultStateReq, SingleXChainMultiVaultStateReq } from "src/types/DataTypes.sol"; +import { MultiVaultSFData, MultiDstMultiVaultStateReq, MultiDstSingleVaultStateReq, SingleXChainMultiVaultStateReq } from "src/types/DataTypes.sol"; import "forge-std/console2.sol"; contract RejectEther { From 4fcfde5c248c18ea165bb1d2e6fd6bf911c6ecdf Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 29 Oct 2024 16:46:34 +0000 Subject: [PATCH 39/44] test: fix rebalanceMultiPositions_multiDstSingleVaultDepositSelector --- Makefile | 2 +- src/router-plus/SuperformRouterPlus.sol | 24 +- .../router-plus/SuperformRouterPlus.t.sol | 209 ++++++++---------- 3 files changed, 108 insertions(+), 127 deletions(-) diff --git a/Makefile b/Makefile index 54531f8a7..d2545a444 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ build-sizes: ## Builds the project and shows sizes .PHONY: test-vvv test-vvv: ## Runs tests with verbose output - forge test --match-test test_rebalanceSinglePosition_multiDstMultiVaultDepositSelector --evm-version cancun -vvv + forge test --match-contract SuperformRouterPlusTest --evm-version cancun .PHONY: ftest ftest: ## Runs tests with cancun evm version diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index ecb460009..44e37e5b0 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -35,7 +35,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) {} + constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { } ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // @@ -453,6 +453,9 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { if (req.superformData.liqRequests[i].liqDstChainId != CHAIN_ID) { revert REBALANCE_MULTI_POSITIONS_DIFFERENT_CHAIN(); } + + console.log("req.superformData.amounts[i]", req.superformData.amounts[i]); + console.log("args.sharesToRedeem[i]", args.sharesToRedeem[i]); if (req.superformData.amounts[i] != args.sharesToRedeem[i]) { revert REBALANCE_MULTI_POSITIONS_DIFFERENT_AMOUNTS(); } @@ -483,6 +486,8 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { uint256 amountIn; bool containsSwapData; + uint256 amountInTemp; + bool containsSwapDataTemp; if (rebalanceToSelector == IBaseRouter.singleDirectSingleVaultDeposit.selector) { SingleVaultSFData memory sfData = @@ -496,38 +501,39 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { MultiVaultSFData memory sfData = abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectMultiVaultStateReq)).superformData; uint256 len = sfData.liqRequests.length; - uint256 amountInTemp; + for (uint256 i; i < len; ++i) { - (amountInTemp, containsSwapData) = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); + (amountInTemp, containsSwapDataTemp) = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); + if (containsSwapDataTemp) containsSwapData = true; amountIn += amountInTemp; } } else if (rebalanceToSelector == IBaseRouter.singleXChainMultiVaultDeposit.selector) { MultiVaultSFData memory sfData = abi.decode(_parseCallData(rebalanceToCallData), (SingleXChainMultiVaultStateReq)).superformsData; uint256 len = sfData.liqRequests.length; - uint256 amountInTemp; for (uint256 i; i < len; ++i) { - (amountInTemp, containsSwapData) = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); + (amountInTemp, containsSwapDataTemp) = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); + if (containsSwapDataTemp) containsSwapData = true; amountIn += amountInTemp; } } else if (rebalanceToSelector == IBaseRouter.multiDstSingleVaultDeposit.selector) { SingleVaultSFData[] memory sfData = abi.decode(_parseCallData(rebalanceToCallData), (MultiDstSingleVaultStateReq)).superformsData; uint256 lenDst = sfData.length; - uint256 amountInTemp; for (uint256 i; i < lenDst; ++i) { - (amountInTemp, containsSwapData) = _takeAmountIn(sfData[i].liqRequest, sfData[i].amount); + (amountInTemp, containsSwapDataTemp) = _takeAmountIn(sfData[i].liqRequest, sfData[i].amount); + if (containsSwapDataTemp) containsSwapData = true; amountIn += amountInTemp; } } else if (rebalanceToSelector == IBaseRouter.multiDstMultiVaultDeposit.selector) { MultiVaultSFData[] memory sfData = abi.decode(_parseCallData(rebalanceToCallData), (MultiDstMultiVaultStateReq)).superformsData; uint256 lenDst = sfData.length; - uint256 amountInTemp; for (uint256 i; i < lenDst; ++i) { uint256 len = sfData[i].liqRequests.length; for (uint256 j; j < len; ++j) { - (amountInTemp, containsSwapData) = _takeAmountIn(sfData[i].liqRequests[j], sfData[i].amounts[j]); + (amountInTemp, containsSwapDataTemp) = _takeAmountIn(sfData[i].liqRequests[j], sfData[i].amounts[j]); + if (containsSwapDataTemp) containsSwapData = true; amountIn += amountInTemp; } } diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 66c3edb6a..0f90eee4f 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -8,7 +8,12 @@ import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAs import { IBaseSuperformRouterPlus } from "src/interfaces/IBaseSuperformRouterPlus.sol"; import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; -import { MultiVaultSFData, MultiDstMultiVaultStateReq, MultiDstSingleVaultStateReq, SingleXChainMultiVaultStateReq } from "src/types/DataTypes.sol"; +import { + MultiVaultSFData, + MultiDstMultiVaultStateReq, + MultiDstSingleVaultStateReq, + SingleXChainMultiVaultStateReq +} from "src/types/DataTypes.sol"; import "forge-std/console2.sol"; contract RejectEther { @@ -508,7 +513,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceSinglePosition_invalidDepositSelector() public { vm.startPrank(deployer); - _directDeposit(superformId1); + _directDeposit(superformId1, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToOneVaultArgs(deployer); @@ -526,7 +531,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceSinglePosition_noSwapData() public { vm.startPrank(deployer); - _directDeposit(superformId1); + _directDeposit(superformId1, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToOneVaultArgs(deployer); @@ -546,7 +551,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceSinglePosition_singleDirectSingleVaultDepositSelector() public { vm.startPrank(deployer); - _directDeposit(superformId1); + _directDeposit(superformId1, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToOneVaultArgs(deployer); @@ -562,7 +567,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceSinglePosition_singleXChainSingleVaultDepositSelector() public { vm.startPrank(deployer); - _directDeposit(superformId1); + _directDeposit(superformId1, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToOneVaultArgs(deployer); @@ -575,17 +580,17 @@ contract SuperformRouterPlusTest is ProtocolActions { assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } - function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { + function test_rebalanceSinglePosition_singleXChainMultiVaultDeposit() public { vm.startPrank(deployer); - _directDeposit(superformId1); - _directDeposit(superformId2); + _directDeposit(superformId1, 1e18); + _directDeposit(superformId2, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToTwoVaultsArgs(); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); - + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); @@ -593,95 +598,66 @@ contract SuperformRouterPlusTest is ProtocolActions { assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } - function test_rebalanceMultiPositions_multiDstSingleVaultDepositSelector() public { - vm.activeFork(); - vm.selectFork(FORKS[SOURCE_CHAIN]); - deal(getContract(SOURCE_CHAIN, "DAI"), deployer, 100e18); - + function test_rebalanceMultiPositions_multiDstSingleVaultDepositSelector() public { vm.startPrank(deployer); - _directDeposit(superformId1); - _directDeposit(superformId2); + _directDeposit(superformId1, 1e18); + _directDeposit(superformId2, 1e6); vm.stopPrank(); uint256[] memory superformIds = new uint256[](2); superformIds[0] = superformId1; superformIds[1] = superformId2; - (address superform1,,) = superformId1.getSuperform(); - (address superform2,,) = superformId2.getSuperform(); - - SingleVaultSFData[] memory superformsData = new SingleVaultSFData[](3); + SingleVaultSFData[] memory superformsData = new SingleVaultSFData[](2); LiqBridgeTxDataArgs memory liqBridgeTxDataArgs1 = LiqBridgeTxDataArgs( 1, getContract(SOURCE_CHAIN, "DAI"), - getContract(SOURCE_CHAIN, "DAI"), - getContract(SOURCE_CHAIN, "DAI"), - superform1, + getContract(SOURCE_CHAIN, "USDC"), + getContract(SOURCE_CHAIN, "USDC"), + superform2, SOURCE_CHAIN, SOURCE_CHAIN, SOURCE_CHAIN, false, - getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), + superform2, uint256(SOURCE_CHAIN), 1e18, // This should be updated with the actual amount if available - true, + false, 0, 1, 1, 1, address(0) ); - + address interimAsset = getContract(SOURCE_CHAIN, "DAI"); + superformsData[0] = SingleVaultSFData({ superformId: superformId1, amount: 1e18, outputAmount: 1e18, maxSlippage: 100, - liqRequest: LiqRequest( - _buildLiqBridgeTxData(liqBridgeTxDataArgs1, false), getContract(SOURCE_CHAIN, "DAI"), address(0), 1, SOURCE_CHAIN, 0 - ), + liqRequest: LiqRequest("", interimAsset, address(0), 1, SOURCE_CHAIN, 0), permit2data: "", hasDstSwap: false, retain4626: false, - receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, + receiverAddress: deployer, receiverAddressSP: deployer, extraFormData: "" }); - LiqBridgeTxDataArgs memory liqBridgeTxDataArgs2 = LiqBridgeTxDataArgs( - 1, - getContract(SOURCE_CHAIN, "DAI"), - getContract(SOURCE_CHAIN, "DAI"), - getContract(SOURCE_CHAIN, "DAI"), - superform2, - SOURCE_CHAIN, - SOURCE_CHAIN, - SOURCE_CHAIN, - false, - getContract(SOURCE_CHAIN, "SuperformRouterPlusAsync"), - uint256(SOURCE_CHAIN), - 1e18, // This should be updated with the actual amount if available - true, - 0, - 1, - 1, - 1, - address(0) - ); - superformsData[1] = SingleVaultSFData({ superformId: superformId2, - amount: 1e18, - outputAmount: 1e18, + amount: 1e6, + outputAmount: 1e6, maxSlippage: 100, liqRequest: LiqRequest( - _buildLiqBridgeTxData(liqBridgeTxDataArgs2, false), getContract(SOURCE_CHAIN, "DAI"), address(0), 1, SOURCE_CHAIN, 0 + _buildLiqBridgeTxData(liqBridgeTxDataArgs1, true), interimAsset, address(0), 1, SOURCE_CHAIN, 0 ), permit2data: "", hasDstSwap: false, retain4626: false, - receiverAddress: ROUTER_PLUS_ASYNC_SOURCE, + receiverAddress: deployer, receiverAddressSP: deployer, extraFormData: "" }); @@ -694,51 +670,37 @@ contract SuperformRouterPlusTest is ProtocolActions { dstChainIds[0] = SOURCE_CHAIN; dstChainIds[1] = SOURCE_CHAIN; - MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq = MultiDstSingleVaultStateReq({ - ambIds: ambIds, - dstChainIds: dstChainIds, - superformsData: superformsData - }); + MultiDstSingleVaultStateReq memory multiDstSingleVaultStateReq = + MultiDstSingleVaultStateReq({ ambIds: ambIds, dstChainIds: dstChainIds, superformsData: superformsData }); uint256[] memory sharesToRedeem = new uint256[](2); sharesToRedeem[0] = 1e18; - sharesToRedeem[1] = 1e18; + sharesToRedeem[1] = 1e6; - ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = - ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = ISuperformRouterPlus + .RebalanceMultiPositionsSyncArgs( superformIds, sharesToRedeem, 1e18, 1 ether, 1 ether, - getContract(SOURCE_CHAIN, "DAI"), + interimAsset, 100, deployer, - // abi.encodeCall( - // IBaseRouter.multiDstSingleVaultDeposit, multiDstSingleVaultStateReq - // ), - _callDataRebalanceFromMultiDst( - getContract(SOURCE_CHAIN, "DAI"), - superformIds, - SOURCE_CHAIN, - SOURCE_CHAIN - ), - abi.encodeCall( - IBaseRouter.multiDstSingleVaultDeposit, MultiDstSingleVaultStateReq - ) - //_buildCallDataRebalanceToSingleVaultFromMultiDst(1e18) - //_callDataRebalanceToSingleVaultFromMultiDst(1e18) + _callDataRebalanceFromTwoVaults(interimAsset), + abi.encodeCall(IBaseRouter.multiDstSingleVaultDeposit, multiDstSingleVaultStateReq) ); vm.startPrank(deployer); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); - + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); vm.stopPrank(); - assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); - assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + /// @dev assert positions preserved to be the same + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 1e18); + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 1e6); } function test_rebalanceMultiPositions_multiDstMultiVaultDepositSelector() public { @@ -939,7 +901,7 @@ contract SuperformRouterPlusTest is ProtocolActions { // vm.startPrank(deployer); // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); - + // SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); // vm.stopPrank(); @@ -952,7 +914,7 @@ contract SuperformRouterPlusTest is ProtocolActions { deal(rejectEther, 3 ether); vm.startPrank(deployer); - _directDeposit(superformId1); + _directDeposit(superformId1, 1e18); SuperPositions(SUPER_POSITIONS_SOURCE).safeTransferFrom(deployer, rejectEther, superformId1, 1e18, abi.encode()); @@ -1000,7 +962,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceSinglePosition_errors() public { vm.startPrank(deployer); - _directDeposit(superformId1); + _directDeposit(superformId1, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToOneVaultArgs(deployer); @@ -1047,8 +1009,8 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceMultiPositions_errors() public { vm.startPrank(deployer); - _directDeposit(superformId1); - _directDeposit(superformId2); + _directDeposit(superformId1, 1e18); + _directDeposit(superformId2, 1e6); (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args,) = _buildRebalanceTwoPositionsToOneVaultXChainArgs(); @@ -1618,8 +1580,8 @@ contract SuperformRouterPlusTest is ProtocolActions { vm.selectFork(FORKS[SOURCE_CHAIN]); // Setup: Create two destination superforms on the same chain - uint256 superformId1 = superformId1; - uint256 superformId2 = superformId1; + uint256 superformId1t = superformId1; + uint256 superformId2t = superformId1; MultiVaultSFData memory sfData = MultiVaultSFData({ superformIds: new uint256[](2), @@ -1635,8 +1597,8 @@ contract SuperformRouterPlusTest is ProtocolActions { extraFormData: "" }); - sfData.superformIds[0] = superformId1; - sfData.superformIds[1] = superformId2; + sfData.superformIds[0] = superformId1t; + sfData.superformIds[1] = superformId2t; sfData.amounts[0] = 5e17; // 0.5 ether sfData.amounts[1] = 5e17; // 0.5 ether sfData.outputAmounts[0] = 5e17; @@ -1704,12 +1666,12 @@ contract SuperformRouterPlusTest is ProtocolActions { // Verify the results assertGt( - SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), + SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1t), 0, "Destination superform 1 balance should be greater than 0" ); assertGt( - SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), + SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2t), 0, "Destination superform 2 balance should be greater than 0" ); @@ -1878,10 +1840,9 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_crossChainRebalance_multiDstMultiVaultDeposit() public { vm.selectFork(FORKS[SOURCE_CHAIN]); - // Setup: Create two destination superforms on the same chain - uint256 superformId1 = superformId1; - uint256 superformId2 = superformId1; + uint256 superformId1t = superformId1; + uint256 superformId2t = superformId1; MultiVaultSFData memory sfData = MultiVaultSFData({ superformIds: new uint256[](2), @@ -1897,8 +1858,8 @@ contract SuperformRouterPlusTest is ProtocolActions { extraFormData: "" }); - sfData.superformIds[0] = superformId1; - sfData.superformIds[1] = superformId2; + sfData.superformIds[0] = superformId1t; + sfData.superformIds[1] = superformId2t; sfData.amounts[0] = 5e17; // 0.5 ether sfData.amounts[1] = 5e17; // 0.5 ether sfData.outputAmounts[0] = 5e17; @@ -2342,7 +2303,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceFromSinglePosition_toOneVault() public { vm.startPrank(deployer); - _directDeposit(superformId1); + _directDeposit(superformId1, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToOneVaultArgs(deployer); @@ -2359,7 +2320,7 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceFromSinglePosition_toTwoVaults() public { vm.startPrank(deployer); - _directDeposit(superformId1); + _directDeposit(superformId1, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = _buildRebalanceSinglePositionToTwoVaultsArgs(); @@ -2376,8 +2337,8 @@ contract SuperformRouterPlusTest is ProtocolActions { function test_rebalanceFromTwoPositions_toOneXChainVault() public { vm.startPrank(deployer); - _directDeposit(superformId1); - _directDeposit(superformId2); + _directDeposit(superformId1, 1e18); + _directDeposit(superformId2, 1e6); (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args, uint256 totalAmountToDeposit) = _buildRebalanceTwoPositionsToOneVaultXChainArgs(); @@ -2936,7 +2897,8 @@ contract SuperformRouterPlusTest is ProtocolActions { // function _buildRebalanceTwoPositionsToTwoVaultsXChainArgs() // internal - // returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args, uint256[] calldata totalAmountToDeposit) + // returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args, uint256[] calldata + // totalAmountToDeposit) // { // args.ids = new uint256[](2); // args.ids[0] = superformId1; @@ -3809,37 +3771,46 @@ contract SuperformRouterPlusTest is ProtocolActions { function _callDataRebalanceFromTwoVaults(address interimToken) internal view returns (bytes memory) { uint256[] memory superformIds = new uint256[](2); - superformIds[0] = superformId1; - superformIds[1] = superformId2; + superformIds[0] = superformId1; // DAI vault + superformIds[1] = superformId2; // USDC vault uint256[] memory amounts = new uint256[](2); amounts[0] = 1e18; - amounts[1] = 1e18; + amounts[1] = 1e6; uint256[] memory outputAmounts = new uint256[](2); outputAmounts[0] = 1e18; - outputAmounts[1] = 1e18; + outputAmounts[1] = 1e6; uint256[] memory maxSlippages = new uint256[](2); maxSlippages[0] = 100; maxSlippages[1] = 100; LiqRequest[] memory liqReqs = new LiqRequest[](2); + /// @dev if interim is USDC then: + /// @dev - vault 1 will have txData (to swap from DAI external token to USDC interim token) + /// @dev - vault 2 will have no txData + /// @dev otherwise, if interim is DAI + /// @dev - vault 1 will have no txData + /// @dev - vault 2 will have txData (to swap from USDC external token to DAI interim token) + /// @dev overriding to false in using withdraw for same chain swap because true likely has issues... LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( 1, - getContract(SOURCE_CHAIN, "DAI"), - getContract(SOURCE_CHAIN, "DAI"), + interimToken == getContract(SOURCE_CHAIN, "USDC") + ? getContract(SOURCE_CHAIN, "DAI") + : getContract(SOURCE_CHAIN, "USDC"), interimToken, - superform1, + interimToken, + interimToken == getContract(SOURCE_CHAIN, "USDC") ? superform1 : superform2, SOURCE_CHAIN, SOURCE_CHAIN, SOURCE_CHAIN, false, getContract(SOURCE_CHAIN, "SuperformRouterPlus"), uint256(SOURCE_CHAIN), - 1e18, + interimToken == getContract(SOURCE_CHAIN, "USDC") ? 1e18 : 1e6, //1e18, - true, + false, /// @dev placeholder value, not used 0, 1, @@ -3848,9 +3819,13 @@ contract SuperformRouterPlusTest is ProtocolActions { address(0) ); - liqReqs[0] = - LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, true), interimToken, address(0), 1, SOURCE_CHAIN, 0); - liqReqs[1] = LiqRequest("", interimToken, address(0), 1, SOURCE_CHAIN, 0); + liqReqs[0] = interimToken == getContract(SOURCE_CHAIN, "USDC") + ? LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, true), interimToken, address(0), 1, SOURCE_CHAIN, 0) + : LiqRequest("", interimToken, address(0), 1, SOURCE_CHAIN, 0); + + liqReqs[1] = interimToken == getContract(SOURCE_CHAIN, "USDC") + ? LiqRequest("", interimToken, address(0), 1, SOURCE_CHAIN, 0) + : LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, true), interimToken, address(0), 1, SOURCE_CHAIN, 0); bool[] memory falseBool = new bool[](2); @@ -4156,14 +4131,14 @@ contract SuperformRouterPlusTest is ProtocolActions { ); } - function _directDeposit(uint256 superformId) internal { + function _directDeposit(uint256 superformId, uint256 amounts) internal { vm.selectFork(FORKS[SOURCE_CHAIN]); (address superform,,) = superformId.getSuperform(); SingleVaultSFData memory data = SingleVaultSFData( superformId, - 1e18, - 1e18, + amounts, + amounts, 100, LiqRequest("", IBaseForm(superform).getVaultAsset(), address(0), 1, SOURCE_CHAIN, 0), "", From bdb146faf4b35a8a9ec8e2ec065f22a3bafebfe8 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:29:00 +0000 Subject: [PATCH 40/44] test: fix test_rebalanceMultiPositions_multiDstMultiVaultDepositSelector --- Makefile | 2 +- src/router-plus/SuperformRouterPlus.sol | 2 - test/mainnet/SmokeTest.Staging.t.sol | 2 - .../router-plus/SuperformRouterPlus.t.sol | 327 +++++++----------- 4 files changed, 125 insertions(+), 208 deletions(-) diff --git a/Makefile b/Makefile index d2545a444..a97c10b4f 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ build-sizes: ## Builds the project and shows sizes .PHONY: test-vvv test-vvv: ## Runs tests with verbose output - forge test --match-contract SuperformRouterPlusTest --evm-version cancun + forge test --match-test test_rebalanceMultiPositions_multiDstMultiVaultDepositSelector --evm-version cancun -vvv .PHONY: ftest ftest: ## Runs tests with cancun evm version diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 44e37e5b0..6046b1b6d 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -454,8 +454,6 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert REBALANCE_MULTI_POSITIONS_DIFFERENT_CHAIN(); } - console.log("req.superformData.amounts[i]", req.superformData.amounts[i]); - console.log("args.sharesToRedeem[i]", args.sharesToRedeem[i]); if (req.superformData.amounts[i] != args.sharesToRedeem[i]) { revert REBALANCE_MULTI_POSITIONS_DIFFERENT_AMOUNTS(); } diff --git a/test/mainnet/SmokeTest.Staging.t.sol b/test/mainnet/SmokeTest.Staging.t.sol index ec8c49af2..2b5521bfc 100644 --- a/test/mainnet/SmokeTest.Staging.t.sol +++ b/test/mainnet/SmokeTest.Staging.t.sol @@ -569,8 +569,6 @@ contract SmokeTestStaging is MainnetBaseSetup { } function test_asyncStateRegistry() public { - AsyncStateRegistry asyncStateRegistry; - for (uint256 i; i < TARGET_DEPLOYMENT_CHAINS.length; ++i) { uint64 chainId = TARGET_DEPLOYMENT_CHAINS[i]; vm.selectFork(FORKS[chainId]); diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 0f90eee4f..77bcfe57d 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -704,209 +704,130 @@ contract SuperformRouterPlusTest is ProtocolActions { } function test_rebalanceMultiPositions_multiDstMultiVaultDepositSelector() public { - // vm.activeFork(); - // vm.selectFork(FORKS[SOURCE_CHAIN]); - // deal(getContract(SOURCE_CHAIN, "DAI"), deployer, 100e18); - - // vm.startPrank(deployer); - // _directDeposit(superformId1); - // _directDeposit(superformId2); - // vm.stopPrank(); - - // uint256[] memory superformIds = new uint256[](2); - // superformIds[0] = superformId1; - // superformIds[1] = superformId2; - - // (address superform1,,) = superformId1.getSuperform(); - // (address superform2,,) = superformId2.getSuperform(); - - // MultiVaultSFData[] memory superformsData = new MultiVaultSFData[](2); - - // uint256[] memory superformIds = new uint256[](1); - // superformIds[0] = superformId1; - // superformIds[1] = superformId2; - - // uint256[] memory amounts = new uint256[](1); - // amounts[0] = 1e18; - // amounts[1] = 1e18; - - // uint256[] memory outputAmounts = new uint256[](1); - // outputAmounts[0] = 1e18; - // outputAmounts[1] = 1e18; - - // uint256[] memory maxSlippages = new uint256[](1); - // maxSlippages[0] = 100; - // maxSlippages[1] = 100; - - // LiqRequest memory liqReq1 = LiqRequest( - // _buildLiqBridgeTxData( - // LiqBridgeTxDataArgs( - // 1, - // getContract(SOURCE_CHAIN, "DAI"), - // getContract(SOURCE_CHAIN, "DAI"), - // getContract(SOURCE_CHAIN, "DAI"), - // superform1, - // SOURCE_CHAIN, - // SOURCE_CHAIN, - // SOURCE_CHAIN, - // false, - // getContract(SOURCE_CHAIN, "CoreStateRegistry"), - // uint256(SOURCE_CHAIN), - // 1e18, - // //1e18, - // false, - // /// @dev placeholder value, not used - // 0, - // 1, - // 1, - // 1, - // address(0) - // ), - // false - // ), - // getContract(SOURCE_CHAIN, "DAI"), - // address(0), - // 1, - // SOURCE_CHAIN, - // 0 - // ); - - // LiqRequest memory liqReq2 = LiqRequest( - // _buildLiqBridgeTxData( - // LiqBridgeTxDataArgs( - // 1, - // getContract(SOURCE_CHAIN, "DAI"), - // getContract(SOURCE_CHAIN, "DAI"), - // getContract(SOURCE_CHAIN, "DAI"), - // superform1, - // SOURCE_CHAIN, - // SOURCE_CHAIN, - // SOURCE_CHAIN, - // false, - // getContract(SOURCE_CHAIN, "CoreStateRegistry"), - // uint256(SOURCE_CHAIN), - // 1e18, - // //1e18, - // false, - // /// @dev placeholder value, not used - // 0, - // 1, - // 1, - // 1, - // address(0) - // ), - // false - // ), - // getContract(SOURCE_CHAIN, "DAI"), - // address(0), - // 1, - // SOURCE_CHAIN, - // 0 - // ); - - // LiqRequest[] memory liqRequests = new LiqRequest[](2); - // liqRequests[0] = liqReq1; - // liqRequests[1] = liqReq2; - - // superformsData[0] = MultiVaultSFData({ - // superformId: superformId1, - // amounts: amounts, - // outputAmounts: outputAmounts, - // maxSlippages: maxSlippages, - // liqRequests: liqRequests, - // permit2data: "", - // hasDstSwap: false, - // retain4626: false, - // receiverAddress: deployer, - // receiverAddressSP: deployer, - // extraFormData: "" - // }); - - // uint256[] memory ids2 = new uint256[](2); - // ids2[0] = superformId3; - // ids2[1] = superformId4; - - // uint256[] memory amounts2 = new uint256[](2); - // amounts2[0] = 1e18; - // amounts2[1] = 1e18; - - // uint256[] memory outputAmounts2 = new uint256[](2); - // outputAmounts2[0] = 1e18; - // outputAmounts2[1] = 1e18; - - // uint256[] memory maxSlippages2 = new uint256[](2); - // maxSlippages2[0] = 100; - // maxSlippages2[1] = 100; - - // LiqRequest[] memory liqRequests2 = new LiqRequest[](2); - // liqRequests2[0] = liqReq1; // ToDo: check - // liqRequests2[1] = liqReq2; - - // superformsData[1] = MultiVaultSFData({ - // superformId: superformId3, - // amounts: amounts2, - // outputAmounts: outputAmounts2, - // maxSlippages: maxSlippages2, - // liqRequests: liqRequests2, - // permit2data: "", - // hasDstSwap: false, - // retain4626: false, - // receiverAddress: deployer, - // receiverAddressSP: deployer, - // extraFormData: "" - // }); - - // uint8[][] memory ambIds = new uint8[][](2); - // ambIds[0] = AMBs; - // ambIds[1] = AMBs; - - // uint64[] memory dstChainIds = new uint64[](2); - // dstChainIds[0] = SOURCE_CHAIN; - // dstChainIds[1] = SOURCE_CHAIN; - - // MultiDstMultiVaultStateReq memory multiDstSingleVaultStateReq = MultiDstMultiVaultStateReq({ - // ambIds: ambIds, - // dstChainIds: dstChainIds, - // superformsData: superformsData - // }); - - // uint256[] memory sharesToRedeem = new uint256[](2); - // sharesToRedeem[0] = 1e18; - // sharesToRedeem[1] = 1e18; - - // ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = - // ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs( - // superformIds, - // sharesToRedeem, - // 1e18, - // 1 ether, - // 1 ether, - // getContract(SOURCE_CHAIN, "DAI"), - // 100, - // deployer, - // // abi.encodeCall( - // // IBaseRouter.multiDstMultiVaultWithdraw, multiDstMultiVaultStateReq - // // ), - // _callDataRebalanceFromMultiDst( - // getContract(SOURCE_CHAIN, "DAI"), - // superformIds, - // SOURCE_CHAIN, - // SOURCE_CHAIN - // ), - // abi.encodeCall( - // IBaseRouter.multiDstMultiVaultDeposit, MultiDstMultiVaultStateReq - // ) - // ); - - // vm.startPrank(deployer); - // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); - // SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); - - // SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); - // vm.stopPrank(); - - // assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); - // assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); + vm.startPrank(deployer); + _directDeposit(superformId1, 1e18); + _directDeposit(superformId2, 1e6); + vm.stopPrank(); + + uint256[] memory superformIds = new uint256[](2); + superformIds[0] = superformId1; + superformIds[1] = superformId2; + + address interimAsset = getContract(SOURCE_CHAIN, "DAI"); + uint256[] memory sfIds = new uint256[](1); + sfIds[0] = superformId1; + + uint256[] memory amounts = new uint256[](1); + amounts[0] = 1e18; + + uint256[] memory slippages = new uint256[](1); + slippages[0] = 100; + + bool[] memory empty = new bool[](1); + + LiqRequest[] memory liqRequests = new LiqRequest[](1); + liqRequests[0] = LiqRequest("", interimAsset, address(0), 1, SOURCE_CHAIN, 0); + + MultiVaultSFData[] memory superformsData = new MultiVaultSFData[](2); + + superformsData[0] = MultiVaultSFData({ + superformIds: sfIds, + amounts: amounts, + outputAmounts: amounts, + maxSlippages: slippages, + liqRequests: liqRequests, + permit2data: "", + hasDstSwaps: empty, + retain4626s: empty, + receiverAddress: deployer, + receiverAddressSP: deployer, + extraFormData: "" + }); + + sfIds = new uint256[](1); + sfIds[0] = superformId2; + + amounts = new uint256[](1); + amounts[0] = 1e6; + + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs1 = LiqBridgeTxDataArgs( + 1, + getContract(SOURCE_CHAIN, "DAI"), + getContract(SOURCE_CHAIN, "USDC"), + getContract(SOURCE_CHAIN, "USDC"), + superform2, + SOURCE_CHAIN, + SOURCE_CHAIN, + SOURCE_CHAIN, + false, + superform2, + uint256(SOURCE_CHAIN), + 1e18, // This should be updated with the actual amount if available + false, + 0, + 1, + 1, + 1, + address(0) + ); + + liqRequests = new LiqRequest[](1); + liqRequests[0] = + LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs1, true), interimAsset, address(0), 1, SOURCE_CHAIN, 0); + + superformsData[1] = MultiVaultSFData({ + superformIds: sfIds, + amounts: amounts, + outputAmounts: amounts, + maxSlippages: slippages, + liqRequests: liqRequests, + permit2data: "", + hasDstSwaps: empty, + retain4626s: empty, + receiverAddress: deployer, + receiverAddressSP: deployer, + extraFormData: "" + }); + + uint8[][] memory ambIds = new uint8[][](2); + ambIds[0] = AMBs; + ambIds[1] = AMBs; + + uint64[] memory dstChainIds = new uint64[](2); + dstChainIds[0] = SOURCE_CHAIN; + dstChainIds[1] = SOURCE_CHAIN; + + MultiDstMultiVaultStateReq memory multiDstMultiVaultStateReq = + MultiDstMultiVaultStateReq({ ambIds: ambIds, dstChainIds: dstChainIds, superformsData: superformsData }); + + uint256[] memory sharesToRedeem = new uint256[](2); + sharesToRedeem[0] = 1e18; + sharesToRedeem[1] = 1e6; + + ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args = ISuperformRouterPlus + .RebalanceMultiPositionsSyncArgs( + superformIds, + sharesToRedeem, + 1e18, + 1 ether, + 1 ether, + interimAsset, + 100, + deployer, + _callDataRebalanceFromTwoVaults(interimAsset), + abi.encodeCall(IBaseRouter.multiDstMultiVaultDeposit, multiDstMultiVaultStateReq) + ); + + vm.startPrank(deployer); + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, 1e18); + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId2, 1e18); + + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); + vm.stopPrank(); + + /// @dev assert positions preserved to be the same + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 1e18); + assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 1e6); } function test_refundUnusedAndResetApprovals_failedToSendNative() public { From 572bc8bfe82cbabd70455c9992813f1edb07cc40 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:38:25 +0000 Subject: [PATCH 41/44] fix: remaining issues --- Makefile | 2 +- src/interfaces/ISuperformRouterPlus.sol | 3 +++ src/router-plus/BaseSuperformRouterPlus.sol | 9 +++++++++ src/router-plus/SuperformRouterPlus.sol | 18 +++++++----------- src/router-plus/SuperformRouterPlusAsync.sol | 7 ------- .../unit/router-plus/SuperformRouterPlus.t.sol | 4 ++-- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index a97c10b4f..633626ebf 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ build-sizes: ## Builds the project and shows sizes .PHONY: test-vvv test-vvv: ## Runs tests with verbose output - forge test --match-test test_rebalanceMultiPositions_multiDstMultiVaultDepositSelector --evm-version cancun -vvv + forge test --match-test test_setGlobalSlippage --evm-version cancun -vvv .PHONY: ftest ftest: ## Runs tests with cancun evm version diff --git a/src/interfaces/ISuperformRouterPlus.sol b/src/interfaces/ISuperformRouterPlus.sol index 759dcf635..3533ec1b6 100644 --- a/src/interfaces/ISuperformRouterPlus.sol +++ b/src/interfaces/ISuperformRouterPlus.sol @@ -49,6 +49,9 @@ interface ISuperformRouterPlus is IBaseSuperformRouterPlus { /// @notice thrown if the amount of assets received is lower than the slippage error ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); + /// @notice thrown if the slippage is invalid + error INVALID_GLOBAL_SLIPPAGE(); + ////////////////////////////////////////////////////////////// // EVENTS // ////////////////////////////////////////////////////////////// diff --git a/src/router-plus/BaseSuperformRouterPlus.sol b/src/router-plus/BaseSuperformRouterPlus.sol index eea99f427..294c1e18c 100644 --- a/src/router-plus/BaseSuperformRouterPlus.sol +++ b/src/router-plus/BaseSuperformRouterPlus.sol @@ -6,6 +6,7 @@ import { IERC1155Receiver } from "openzeppelin-contracts/contracts/token/ERC1155 import { IERC165 } from "openzeppelin-contracts/contracts/utils/introspection/IERC165.sol"; import { IERC20 } from "openzeppelin-contracts/contracts/interfaces/IERC20.sol"; import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; +import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { ISuperRegistry } from "src/interfaces/ISuperRegistry.sol"; import { IBaseSuperformRouterPlus } from "src/interfaces/IBaseSuperformRouterPlus.sol"; @@ -143,4 +144,12 @@ abstract contract BaseSuperformRouterPlus is IBaseSuperformRouterPlus, IERC1155R function _getAddress(bytes32 id_) internal view returns (address) { return superRegistry.getAddress(id_); } + + /// @dev returns if an address has a specific role + /// @param id_ the role id + /// @param addressToCheck_ the address to check + /// @return true if the address has the role, false otherwise + function _hasRole(bytes32 id_, address addressToCheck_) internal view returns (bool) { + return ISuperRBAC(superRegistry.getAddress(keccak256("SUPER_RBAC"))).hasRole(id_, addressToCheck_); + } } diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 6046b1b6d..bb1eac490 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -19,7 +19,6 @@ import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ISuperformRouterPlus, IERC20 } from "src/interfaces/ISuperformRouterPlus.sol"; import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAsync.sol"; import { LiqRequest } from "src/types/DataTypes.sol"; -import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { IBridgeValidator } from "src/interfaces/IBridgeValidator.sol"; /// @title SuperformRouterPlus @@ -35,7 +34,10 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { // CONSTRUCTOR // ////////////////////////////////////////////////////////////// - constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { } + constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { + /// @dev default to 1% slippage as a start + GLOBAL_SLIPPAGE = 100; + } ////////////////////////////////////////////////////////////// // EXTERNAL WRITE FUNCTIONS // @@ -399,7 +401,9 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert Error.NOT_PRIVILEGED_CALLER(keccak256("EMERGENCY_ADMIN_ROLE")); } - require(slippage_ <= ENTIRE_SLIPPAGE && slippage_ > 0, "Invalid slippage"); + if (slippage_ > ENTIRE_SLIPPAGE || slippage_ == 0) { + revert INVALID_GLOBAL_SLIPPAGE(); + } GLOBAL_SLIPPAGE = slippage_; } @@ -691,12 +695,4 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { } } } - - /// @dev returns if an address has a specific role - /// @param id_ the role id - /// @param addressToCheck_ the address to check - /// @return true if the address has the role, false otherwise - function _hasRole(bytes32 id_, address addressToCheck_) internal view returns (bool) { - return ISuperRBAC(superRegistry.getAddress(keccak256("SUPER_RBAC"))).hasRole(id_, addressToCheck_); - } } diff --git a/src/router-plus/SuperformRouterPlusAsync.sol b/src/router-plus/SuperformRouterPlusAsync.sol index 550c1cab2..2357fbf76 100644 --- a/src/router-plus/SuperformRouterPlusAsync.sol +++ b/src/router-plus/SuperformRouterPlusAsync.sol @@ -17,7 +17,6 @@ import { } from "src/router-plus/BaseSuperformRouterPlus.sol"; import { IBaseRouter } from "src/interfaces/IBaseRouter.sol"; import { ISuperformRouterPlusAsync } from "src/interfaces/ISuperformRouterPlusAsync.sol"; -import { ISuperRBAC } from "src/interfaces/ISuperRBAC.sol"; import { SuperformFactory } from "src/SuperformFactory.sol"; /// @title SuperformRouterPlusAsync @@ -537,12 +536,6 @@ contract SuperformRouterPlusAsync is ISuperformRouterPlusAsync, BaseSuperformRou return sfData; } - /// @dev returns if an address has a specific role - - function _hasRole(bytes32 id_, address addressToCheck_) internal view returns (bool) { - return ISuperRBAC(superRegistry.getAddress(keccak256("SUPER_RBAC"))).hasRole(id_, addressToCheck_); - } - function _castToMultiVaultData(SingleVaultSFData memory data_) internal pure diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 77bcfe57d..29775afbf 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -4510,13 +4510,13 @@ contract SuperformRouterPlusTest is ProtocolActions { // Test slippage greater than ENTIRE_SLIPPAGE vm.startPrank(deployer); - vm.expectRevert(); + vm.expectRevert(ISuperformRouterPlus.INVALID_GLOBAL_SLIPPAGE.selector); SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(1_000_000); vm.stopPrank(); // Test slippage 0 vm.startPrank(deployer); - vm.expectRevert(); + vm.expectRevert(ISuperformRouterPlus.INVALID_GLOBAL_SLIPPAGE.selector); SuperformRouterPlus(getContract(SOURCE_CHAIN, "SuperformRouterPlus")).setGlobalSlippage(0); vm.stopPrank(); From 0d7ea697582a91ecb9c8114313ace6c1d3a2098b Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:13:34 +0000 Subject: [PATCH 42/44] fix: internalize approvals fix and add to deposit4626 --- Makefile | 2 +- src/interfaces/ISuperformRouterPlus.sol | 4 + src/router-plus/SuperformRouterPlus.sol | 167 ++++++++------- .../router-plus/SuperformRouterPlus.t.sol | 190 +++++++++++++----- 4 files changed, 233 insertions(+), 130 deletions(-) diff --git a/Makefile b/Makefile index 893efa613..03b2017b0 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ build-sizes: ## Builds the project and shows sizes .PHONY: test-vvv test-vvv: ## Runs tests with verbose output - forge test --match-test test_setGlobalSlippage --evm-version cancun -vvv + forge test --match-test test_rebalanceSinglePosition_singleXChainMultiVaultDeposit --evm-version cancun -vvv .PHONY: ftest diff --git a/src/interfaces/ISuperformRouterPlus.sol b/src/interfaces/ISuperformRouterPlus.sol index 657a56257..005304367 100644 --- a/src/interfaces/ISuperformRouterPlus.sol +++ b/src/interfaces/ISuperformRouterPlus.sol @@ -48,11 +48,15 @@ interface ISuperformRouterPlus is IBaseSuperformRouterPlus { /// @notice thrown if the amount of assets received is lower than the slippage error ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); + /// @notice thrown if the slippage is invalid error INVALID_GLOBAL_SLIPPAGE(); + /// @notice thrown if the tolerance is exceeded during shares redemption error TOLERANCE_EXCEEDED(); + /// @notice thrown if the amountIn is not equal or lower than the balance available + error AMOUNT_IN_NOT_EQUAL_OR_LOWER_THAN_BALANCE(); ////////////////////////////////////////////////////////////// // EVENTS // diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index a9417b05a..02357e423 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -38,8 +38,8 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { ////////////////////////////////////////////////////////////// constructor(address superRegistry_) BaseSuperformRouterPlus(superRegistry_) { - /// @dev default to 1% slippage as a start - GLOBAL_SLIPPAGE = 100; + /// @dev default to 0.1% slippage as a start + GLOBAL_SLIPPAGE = 10; } ////////////////////////////////////////////////////////////// @@ -363,9 +363,8 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { /// @inheritdoc ISuperformRouterPlus function deposit4626(address[] calldata vaults_, Deposit4626Args[] calldata args) external payable { - uint256 length = vaults_.length; - + if (length != args.length) { revert Error.ARRAY_LENGTH_MISMATCH(); } @@ -481,90 +480,17 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { revert Error.VAULT_IMPLEMENTATION_FAILED(); } - bytes4 rebalanceToSelector = _parseSelectorMem(rebalanceToCallData); - /// @dev step 3: rebalance into a new superform with rebalanceCallData - if (!whitelistedSelectors[Actions.DEPOSIT][rebalanceToSelector]) { - revert INVALID_DEPOSIT_SELECTOR(); - } - - uint256 amountIn; - bool containsSwapData; - uint256 amountInTemp; - bool containsSwapDataTemp; - - if (rebalanceToSelector == IBaseRouter.singleDirectSingleVaultDeposit.selector) { - SingleVaultSFData memory sfData = - abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData; - (amountIn, containsSwapData) = _takeAmountIn(sfData.liqRequest, sfData.amount); - } else if (rebalanceToSelector == IBaseRouter.singleXChainSingleVaultDeposit.selector) { - SingleVaultSFData memory sfData = - abi.decode(_parseCallData(rebalanceToCallData), (SingleXChainSingleVaultStateReq)).superformData; - (amountIn, containsSwapData) = _takeAmountIn(sfData.liqRequest, sfData.amount); - } else if (rebalanceToSelector == IBaseRouter.singleDirectMultiVaultDeposit.selector) { - MultiVaultSFData memory sfData = - abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectMultiVaultStateReq)).superformData; - uint256 len = sfData.liqRequests.length; - - for (uint256 i; i < len; ++i) { - (amountInTemp, containsSwapDataTemp) = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); - if (containsSwapDataTemp) containsSwapData = true; - amountIn += amountInTemp; - } - } else if (rebalanceToSelector == IBaseRouter.singleXChainMultiVaultDeposit.selector) { - MultiVaultSFData memory sfData = - abi.decode(_parseCallData(rebalanceToCallData), (SingleXChainMultiVaultStateReq)).superformsData; - uint256 len = sfData.liqRequests.length; - for (uint256 i; i < len; ++i) { - (amountInTemp, containsSwapDataTemp) = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); - if (containsSwapDataTemp) containsSwapData = true; - amountIn += amountInTemp; - } - } else if (rebalanceToSelector == IBaseRouter.multiDstSingleVaultDeposit.selector) { - SingleVaultSFData[] memory sfData = - abi.decode(_parseCallData(rebalanceToCallData), (MultiDstSingleVaultStateReq)).superformsData; - uint256 lenDst = sfData.length; - for (uint256 i; i < lenDst; ++i) { - (amountInTemp, containsSwapDataTemp) = _takeAmountIn(sfData[i].liqRequest, sfData[i].amount); - if (containsSwapDataTemp) containsSwapData = true; - amountIn += amountInTemp; - } - } else if (rebalanceToSelector == IBaseRouter.multiDstMultiVaultDeposit.selector) { - MultiVaultSFData[] memory sfData = - abi.decode(_parseCallData(rebalanceToCallData), (MultiDstMultiVaultStateReq)).superformsData; - uint256 lenDst = sfData.length; - for (uint256 i; i < lenDst; ++i) { - uint256 len = sfData[i].liqRequests.length; - for (uint256 j; j < len; ++j) { - (amountInTemp, containsSwapDataTemp) = _takeAmountIn(sfData[i].liqRequests[j], sfData[i].amounts[j]); - if (containsSwapDataTemp) containsSwapData = true; - amountIn += amountInTemp; - } - } - } - - if (containsSwapData) { - if (ENTIRE_SLIPPAGE * amountToDeposit < ((amountIn * (ENTIRE_SLIPPAGE - GLOBAL_SLIPPAGE)))) { - revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); - } - } + uint256 amountIn = _validateAndGetAmountIn(rebalanceToCallData, amountToDeposit); _deposit(router_, interimAsset, amountIn, args.rebalanceToMsgValue, rebalanceToCallData); } - function _takeAmountIn( - LiqRequest memory liqReq, - uint256 sfDataAmount - ) - internal - view - returns (uint256 amountIn, bool containsSwapData) - { + function _takeAmountIn(LiqRequest memory liqReq, uint256 sfDataAmount) internal view returns (uint256 amountIn) { bytes memory txData = liqReq.txData; if (txData.length == 0) { amountIn = sfDataAmount; } else { amountIn = IBridgeValidator(superRegistry.getBridgeValidator(liqReq.bridgeId)).decodeAmountIn(txData, false); - containsSwapData = true; } } @@ -622,9 +548,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { if (assets < TOLERANCE_CONSTANT || balanceDifference < assets - TOLERANCE_CONSTANT) revert TOLERANCE_EXCEEDED(); /// @dev validate the slippage - if ( - (ENTIRE_SLIPPAGE * assets < ((expectedOutputAmount_ * (ENTIRE_SLIPPAGE - maxSlippage_)))) - ) { + if ((ENTIRE_SLIPPAGE * assets < ((expectedOutputAmount_ * (ENTIRE_SLIPPAGE - maxSlippage_))))) { revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); } } @@ -703,7 +627,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { /// @notice deposits ERC4626 vault shares into superform /// @param vault_ The ERC4626 vault to redeem from /// @param args Rest of the arguments to deposit 4626 - function _deposit4626(address vault_, Deposit4626Args calldata args, uint256 arrayLength) internal { + function _deposit4626(address vault_, Deposit4626Args calldata args, uint256 arrayLength) internal { _transferERC20In(IERC20(vault_), args.receiverAddressSP, args.amount); IERC4626 vault = IERC4626(vault_); address assetAdr = vault.asset(); @@ -713,12 +637,87 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { uint256 amountRedeemed = _redeemShare(vault, assetAdr, args.amount, args.expectedOutputAmount, args.maxSlippage); + uint256 amountIn = _validateAndGetAmountIn(args.depositCallData, amountRedeemed); + uint256 msgValue = msg.value / arrayLength; address router = _getAddress(keccak256("SUPERFORM_ROUTER")); - _deposit(router, asset, amountRedeemed, msgValue, args.depositCallData); + + _deposit(router, asset, amountIn, msgValue, args.depositCallData); _tokenRefunds(router, assetAdr, args.receiverAddressSP, balanceBefore); emit Deposit4626Completed(args.receiverAddressSP, vault_); } + + function _validateAndGetAmountIn( + bytes calldata rebalanceToCallData, + uint256 amountToDeposit + ) + internal + view + returns (uint256 amountIn) + { + bytes4 rebalanceToSelector = _parseSelectorMem(rebalanceToCallData); + + if (!whitelistedSelectors[Actions.DEPOSIT][rebalanceToSelector]) { + revert INVALID_DEPOSIT_SELECTOR(); + } + + uint256 amountInTemp; + + if (rebalanceToSelector == IBaseRouter.singleDirectSingleVaultDeposit.selector) { + SingleVaultSFData memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData; + amountIn = _takeAmountIn(sfData.liqRequest, sfData.amount); + } else if (rebalanceToSelector == IBaseRouter.singleXChainSingleVaultDeposit.selector) { + SingleVaultSFData memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (SingleXChainSingleVaultStateReq)).superformData; + amountIn = _takeAmountIn(sfData.liqRequest, sfData.amount); + } else if (rebalanceToSelector == IBaseRouter.singleDirectMultiVaultDeposit.selector) { + MultiVaultSFData memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (SingleDirectMultiVaultStateReq)).superformData; + uint256 len = sfData.liqRequests.length; + + for (uint256 i; i < len; ++i) { + amountInTemp = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); + amountIn += amountInTemp; + } + } else if (rebalanceToSelector == IBaseRouter.singleXChainMultiVaultDeposit.selector) { + MultiVaultSFData memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (SingleXChainMultiVaultStateReq)).superformsData; + uint256 len = sfData.liqRequests.length; + for (uint256 i; i < len; ++i) { + amountInTemp = _takeAmountIn(sfData.liqRequests[i], sfData.amounts[i]); + amountIn += amountInTemp; + } + } else if (rebalanceToSelector == IBaseRouter.multiDstSingleVaultDeposit.selector) { + SingleVaultSFData[] memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (MultiDstSingleVaultStateReq)).superformsData; + uint256 lenDst = sfData.length; + for (uint256 i; i < lenDst; ++i) { + amountInTemp = _takeAmountIn(sfData[i].liqRequest, sfData[i].amount); + amountIn += amountInTemp; + } + } else if (rebalanceToSelector == IBaseRouter.multiDstMultiVaultDeposit.selector) { + MultiVaultSFData[] memory sfData = + abi.decode(_parseCallData(rebalanceToCallData), (MultiDstMultiVaultStateReq)).superformsData; + uint256 lenDst = sfData.length; + for (uint256 i; i < lenDst; ++i) { + uint256 len = sfData[i].liqRequests.length; + for (uint256 j; j < len; ++j) { + amountInTemp = _takeAmountIn(sfData[i].liqRequests[j], sfData[i].amounts[j]); + amountIn += amountInTemp; + } + } + } + + /// @dev amountIn must be artificially off-chain reduced to be less than amountToDeposit otherwise the approval + /// @dev to transfer tokens to SuperformRouter won't work + if (amountIn > amountToDeposit) revert AMOUNT_IN_NOT_EQUAL_OR_LOWER_THAN_BALANCE(); + + /// @dev check against a GLOBAL_SLIPPAGE to prevent a malicious keeper from sending a low amountIn + if (ENTIRE_SLIPPAGE * amountToDeposit < ((amountIn * (ENTIRE_SLIPPAGE - GLOBAL_SLIPPAGE)))) { + revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); + } + } } diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 830d3c67a..54edf0ff3 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -681,6 +681,43 @@ contract SuperformRouterPlusTest is ProtocolActions { assertGt(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2), 0); } + function test_rebalanceSinglePosition_0Amount() public { + vm.startPrank(deployer); + + _directDeposit(superformId1, 1e18); + + ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = + _buildRebalanceSinglePositionToOneVaultArgs(deployer); + + bytes memory emptyData; + + SingleVaultSFData memory sfDataRebalanceFrom = + abi.decode(_parseCallData(args.callData), (SingleDirectSingleVaultStateReq)).superformData; + sfDataRebalanceFrom.liqRequest.txData = emptyData; + + args.callData = abi.encodeCall( + IBaseRouter.singleDirectSingleVaultWithdraw, SingleDirectSingleVaultStateReq(sfDataRebalanceFrom) + ); + + SingleVaultSFData memory sfDataRebalanceTo = + abi.decode(_parseCallData(args.rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData; + sfDataRebalanceTo.liqRequest.txData = emptyData; + + args.rebalanceToCallData = abi.encodeCall( + IBaseRouter.singleDirectSingleVaultDeposit, SingleDirectSingleVaultStateReq(sfDataRebalanceTo) + ); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + // mock interim asset to have a balance of 0 on router plus source + vm.mockCall( + args.interimAsset, + abi.encodeWithSelector(IERC20.balanceOf.selector, address(ROUTER_PLUS_SOURCE)), + abi.encode(0) + ); + vm.expectRevert(Error.ZERO_AMOUNT.selector); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + } + function test_rebalanceSinglePosition_singleDirectSingleVaultDepositSelector() public { vm.startPrank(deployer); @@ -720,7 +757,7 @@ contract SuperformRouterPlusTest is ProtocolActions { _directDeposit(superformId2, 1e18); ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = - _buildRebalanceSinglePositionToTwoVaultsArgs(); + _buildRebalanceSinglePositionToTwoVaultsXChainArgs(); SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); @@ -3176,50 +3213,32 @@ contract SuperformRouterPlusTest is ProtocolActions { args.rebalanceToCallData = _callDataRebalanceToOneVaultxChain(totalAmountToDeposit, args.interimAsset); } - // function _buildRebalanceTwoPositionsToTwoVaultsXChainArgs() - // internal - // returns (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args, uint256[] calldata - // totalAmountToDeposit) - // { - // args.ids = new uint256[](2); - // args.ids[0] = superformId1; - // args.ids[1] = superformId2; - - // args.sharesToRedeem = new uint256[](2); - // args.sharesToRedeem[0] = SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1); - // args.sharesToRedeem[1] = SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId2); - - // args.rebalanceFromMsgValue = 1 ether; - // args.rebalanceToMsgValue = 1 ether; - // args.interimAsset = getContract(SOURCE_CHAIN, "USDC"); - // args.slippage = 100; - // args.receiverAddressSP = deployer; - // args.callData = _callDataRebalanceFromTwoVaults(args.interimAsset); - - // uint256 decimal1 = MockERC20(getContract(SOURCE_CHAIN, "DAI")).decimals(); - // uint256 decimal2 = MockERC20(args.interimAsset).decimals(); - // uint256 previewRedeemAmount1 = IBaseForm(superform1).previewRedeemFrom(args.sharesToRedeem[0]); - - // uint256 expectedAmountToReceivePostRebalanceFrom1; - // if (decimal1 > decimal2) { - // expectedAmountToReceivePostRebalanceFrom1 = previewRedeemAmount1 / (10 ** (decimal1 - decimal2)); - // } else { - // expectedAmountToReceivePostRebalanceFrom1 = previewRedeemAmount1 * 10 ** (decimal2 - decimal1); - // } - - // uint256 previewRedeemAmount2 = IBaseForm(superform2).previewRedeemFrom(args.sharesToRedeem[1]); - - // uint256 expectedAmountToReceivePostRebalanceFrom2; - // if (decimal1 > decimal2) { - // expectedAmountToReceivePostRebalanceFrom2 = previewRedeemAmount2 / (10 ** (decimal1 - decimal2)); - // } else { - // expectedAmountToReceivePostRebalanceFrom2 = previewRedeemAmount2 * 10 ** (decimal2 - decimal1); - // } - - // totalAmountToDeposit = expectedAmountToReceivePostRebalanceFrom1 + expectedAmountToReceivePostRebalanceFrom2; - - // args.rebalanceToCallData = _callDataRebalanceToOneVaultxChain(totalAmountToDeposit, args.interimAsset); - // } + function _buildRebalanceSinglePositionToTwoVaultsXChainArgs() + internal + returns (ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args) + { + args.id = superformId1; + args.sharesToRedeem = SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1); + args.rebalanceFromMsgValue = 1 ether; + args.rebalanceToMsgValue = 1 ether; + args.interimAsset = getContract(SOURCE_CHAIN, "USDC"); + args.slippage = 100; + args.receiverAddressSP = deployer; + args.callData = _callDataRebalanceFrom(args.interimAsset); + + uint256 decimal1 = MockERC20(getContract(SOURCE_CHAIN, "DAI")).decimals(); + uint256 decimal2 = MockERC20(args.interimAsset).decimals(); + uint256 previewRedeemAmount = IBaseForm(superform1).previewRedeemFrom(args.sharesToRedeem); + + if (decimal1 > decimal2) { + args.expectedAmountToReceivePostRebalanceFrom = previewRedeemAmount / (10 ** (decimal1 - decimal2)); + } else { + args.expectedAmountToReceivePostRebalanceFrom = previewRedeemAmount * 10 ** (decimal2 - decimal1); + } + + args.rebalanceToCallData = + _callDataRebalanceToTwoVaultxChain(args.expectedAmountToReceivePostRebalanceFrom, args.interimAsset); + } function _buildInitiateXChainRebalanceArgs( uint64 REBALANCE_FROM, @@ -4223,6 +4242,87 @@ contract SuperformRouterPlusTest is ProtocolActions { return abi.encodeCall(IBaseRouter.singleDirectMultiVaultDeposit, SingleDirectMultiVaultStateReq(data)); } + function _callDataRebalanceToTwoVaultxChain( + uint256 amountToDeposit, + address interimToken + ) + internal + returns (bytes memory) + { + uint256 initialFork = vm.activeFork(); + vm.selectFork(FORKS[OP]); + + uint256[] memory superformIds = new uint256[](2); + superformIds[0] = superformId4OP; + superformIds[1] = superformId4OP; + + uint256[] memory amounts = new uint256[](2); + amounts[0] = amountToDeposit / 2; + amounts[1] = amountToDeposit / 2; + + uint256[] memory outputAmounts = new uint256[](2); + outputAmounts[0] = IBaseForm(superform4OP).previewDepositTo(amounts[0]); + outputAmounts[1] = IBaseForm(superform4OP).previewDepositTo(amounts[1]); + + uint256[] memory maxSlippages = new uint256[](2); + maxSlippages[0] = 100; + maxSlippages[1] = 100; + + address underlyingToken = IBaseForm(superform4OP).getVaultAsset(); + LiqBridgeTxDataArgs memory liqBridgeTxDataArgs = LiqBridgeTxDataArgs( + 1, + interimToken, + interimToken, + underlyingToken, + getContract(SOURCE_CHAIN, "SuperformRouter"), + SOURCE_CHAIN, + OP, + OP, + false, + getContract(OP, "CoreStateRegistry"), + uint256(OP), + amounts[1], + //1e18, + false, + /// @dev placeholder value, not used + 0, + 1, + 1, + 1, + address(0) + ); + LiqRequest[] memory liqReqs = new LiqRequest[](2); + + liqReqs[0] = LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, false), interimToken, address(0), 1, OP, 0); + liqReqs[1] = LiqRequest(_buildLiqBridgeTxData(liqBridgeTxDataArgs, false), interimToken, address(0), 1, OP, 0); + + bool[] memory falseBoolean = new bool[](2); + + MultiVaultSFData memory data = MultiVaultSFData( + superformIds, + amounts, + outputAmounts, + maxSlippages, + liqReqs, + "", + falseBoolean, + falseBoolean, + deployer, + deployer, + "" + ); + + uint8[] memory ambIds = new uint8[](2); + ambIds[0] = 5; + ambIds[1] = 6; + + uint64 dstChainId = OP; + vm.selectFork(initialFork); + return abi.encodeCall( + IBaseRouter.singleXChainMultiVaultDeposit, SingleXChainMultiVaultStateReq(ambIds, dstChainId, data) + ); + } + function _callDataRebalanceToOneVaultxChain( uint256 amountToDeposit, address interimToken From 86e76c5332a65795f0cde03e5ff0a8db54500231 Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:14:22 +0000 Subject: [PATCH 43/44] fix: slippage check in wrong order --- Makefile | 2 +- src/router-plus/SuperformRouterPlus.sol | 21 ++--- .../router-plus/SuperformRouterPlus.t.sol | 87 +++++++++++++++++-- 3 files changed, 92 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 03b2017b0..281b05636 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,7 @@ build-sizes: ## Builds the project and shows sizes .PHONY: test-vvv test-vvv: ## Runs tests with verbose output - forge test --match-test test_rebalanceSinglePosition_singleXChainMultiVaultDeposit --evm-version cancun -vvv + forge test --match-contract SuperformRouterPlusTest --evm-version cancun .PHONY: ftest diff --git a/src/router-plus/SuperformRouterPlus.sol b/src/router-plus/SuperformRouterPlus.sol index 02357e423..a3d379e45 100644 --- a/src/router-plus/SuperformRouterPlus.sol +++ b/src/router-plus/SuperformRouterPlus.sol @@ -469,18 +469,18 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { /// @dev send SPs to router _callSuperformRouter(router_, callData, args.rebalanceFromMsgValue); - uint256 amountToDeposit = interimAsset.balanceOf(address(this)) - args.balanceBefore; + uint256 availableBalanceToDeposit = interimAsset.balanceOf(address(this)) - args.balanceBefore; - if (amountToDeposit == 0) revert Error.ZERO_AMOUNT(); + if (availableBalanceToDeposit == 0) revert Error.ZERO_AMOUNT(); if ( - ENTIRE_SLIPPAGE * amountToDeposit + ENTIRE_SLIPPAGE * availableBalanceToDeposit < ((args.expectedAmountToReceivePostRebalanceFrom * (ENTIRE_SLIPPAGE - args.slippage))) ) { revert Error.VAULT_IMPLEMENTATION_FAILED(); } - uint256 amountIn = _validateAndGetAmountIn(rebalanceToCallData, amountToDeposit); + uint256 amountIn = _validateAndGetAmountIn(rebalanceToCallData, availableBalanceToDeposit); _deposit(router_, interimAsset, amountIn, args.rebalanceToMsgValue, rebalanceToCallData); } @@ -651,7 +651,7 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { function _validateAndGetAmountIn( bytes calldata rebalanceToCallData, - uint256 amountToDeposit + uint256 availableBalanceToDeposit ) internal view @@ -711,12 +711,13 @@ contract SuperformRouterPlus is ISuperformRouterPlus, BaseSuperformRouterPlus { } } - /// @dev amountIn must be artificially off-chain reduced to be less than amountToDeposit otherwise the approval - /// @dev to transfer tokens to SuperformRouter won't work - if (amountIn > amountToDeposit) revert AMOUNT_IN_NOT_EQUAL_OR_LOWER_THAN_BALANCE(); + /// @dev amountIn must be artificially off-chain reduced to be less than availableBalanceToDeposit otherwise the + /// @dev approval to transfer tokens to SuperformRouter won't work + if (amountIn > availableBalanceToDeposit) revert AMOUNT_IN_NOT_EQUAL_OR_LOWER_THAN_BALANCE(); - /// @dev check against a GLOBAL_SLIPPAGE to prevent a malicious keeper from sending a low amountIn - if (ENTIRE_SLIPPAGE * amountToDeposit < ((amountIn * (ENTIRE_SLIPPAGE - GLOBAL_SLIPPAGE)))) { + /// @dev check amountIn against availableBalanceToDeposit (available balance) via a GLOBAL_SLIPPAGE to prevent a + /// @dev malicious keeper from sending a low amountIn + if (ENTIRE_SLIPPAGE * amountIn < ((availableBalanceToDeposit * (ENTIRE_SLIPPAGE - GLOBAL_SLIPPAGE)))) { revert ASSETS_RECEIVED_OUT_OF_SLIPPAGE(); } } diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index 54edf0ff3..ca9ec4106 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -734,6 +734,78 @@ contract SuperformRouterPlusTest is ProtocolActions { assertEq(SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(deployer, superformId1), 0); } + function test_revert_AMOUNT_IN_NOT_EQUAL_OR_LOWER_THAN_BALANCE() public { + vm.startPrank(deployer); + + _directDeposit(superformId1, 1e18); + + ISuperformRouterPlus.RebalanceSinglePositionSyncArgs memory args = + _buildRebalanceSinglePositionToOneVaultArgs(deployer); + + SingleVaultSFData memory sfDataRebalanceTo = + abi.decode(_parseCallData(args.rebalanceToCallData), (SingleDirectSingleVaultStateReq)).superformData; + sfDataRebalanceTo.amount = 1e30; + + args.rebalanceToCallData = abi.encodeCall( + IBaseRouter.singleDirectSingleVaultDeposit, SingleDirectSingleVaultStateReq(sfDataRebalanceTo) + ); + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance(ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem); + + vm.expectRevert(ISuperformRouterPlus.AMOUNT_IN_NOT_EQUAL_OR_LOWER_THAN_BALANCE.selector); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceSinglePosition{ value: 2 ether }(args); + } + + function test_revert_ASSETS_RECEIVED_OUT_OF_SLIPPAGE() public { + vm.startPrank(deployer); + + _directDeposit(superformId1, 1e18); + _directDeposit(superformId2, 1e6); + + (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args, uint256 totalAmountToDeposit) = + _buildRebalanceTwoPositionsToOneVaultXChainArgs(); + + SingleVaultSFData memory sfDataRebalanceTo = + abi.decode(_parseCallData(args.rebalanceToCallData), (SingleXChainSingleVaultStateReq)).superformData; + + /// @dev keeper attempting to rug the user by reducing amount in + sfDataRebalanceTo.liqRequest.txData = _buildLiqBridgeTxData( + LiqBridgeTxDataArgs( + 1, + args.interimAsset, + getContract(OP, "DAI"), + getContract(OP, "DAI"), + getContract(SOURCE_CHAIN, "SuperformRouter"), + SOURCE_CHAIN, + OP, + OP, + false, + getContract(OP, "CoreStateRegistry"), + uint256(OP), + totalAmountToDeposit - 5e5, + false, + 0, + 1, + 1, + 1, + address(0) + ), + false + ); + + args.rebalanceToCallData = abi.encodeCall( + IBaseRouter.singleXChainSingleVaultDeposit, SingleXChainSingleVaultStateReq(AMBs, OP, sfDataRebalanceTo) + ); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance( + ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem[0] + ); + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance( + ROUTER_PLUS_SOURCE, superformId2, args.sharesToRedeem[1] + ); + vm.expectRevert(ISuperformRouterPlus.ASSETS_RECEIVED_OUT_OF_SLIPPAGE.selector); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); + } + function test_rebalanceSinglePosition_singleXChainSingleVaultDepositSelector() public { vm.startPrank(deployer); @@ -3189,23 +3261,24 @@ contract SuperformRouterPlusTest is ProtocolActions { args.callData = _callDataRebalanceFromTwoVaults(args.interimAsset); uint256 decimal1 = MockERC20(getContract(SOURCE_CHAIN, "DAI")).decimals(); - uint256 decimal2 = MockERC20(args.interimAsset).decimals(); + uint256 decimal2 = MockERC20(getContract(SOURCE_CHAIN, "USDC")).decimals(); + uint256 decimalInterim = MockERC20(args.interimAsset).decimals(); uint256 previewRedeemAmount1 = IBaseForm(superform1).previewRedeemFrom(args.sharesToRedeem[0]); uint256 expectedAmountToReceivePostRebalanceFrom1; - if (decimal1 > decimal2) { - expectedAmountToReceivePostRebalanceFrom1 = previewRedeemAmount1 / (10 ** (decimal1 - decimal2)); + if (decimal1 > decimalInterim) { + expectedAmountToReceivePostRebalanceFrom1 = previewRedeemAmount1 / (10 ** (decimal1 - decimalInterim)); } else { - expectedAmountToReceivePostRebalanceFrom1 = previewRedeemAmount1 * 10 ** (decimal2 - decimal1); + expectedAmountToReceivePostRebalanceFrom1 = previewRedeemAmount1 * 10 ** (decimalInterim - decimal1); } uint256 previewRedeemAmount2 = IBaseForm(superform2).previewRedeemFrom(args.sharesToRedeem[1]); uint256 expectedAmountToReceivePostRebalanceFrom2; - if (decimal1 > decimal2) { - expectedAmountToReceivePostRebalanceFrom2 = previewRedeemAmount2 / (10 ** (decimal1 - decimal2)); + if (decimal2 > decimalInterim) { + expectedAmountToReceivePostRebalanceFrom2 = previewRedeemAmount2 / (10 ** (decimal2 - decimalInterim)); } else { - expectedAmountToReceivePostRebalanceFrom2 = previewRedeemAmount2 * 10 ** (decimal2 - decimal1); + expectedAmountToReceivePostRebalanceFrom2 = previewRedeemAmount2 * 10 ** (decimalInterim - decimal2); } totalAmountToDeposit = expectedAmountToReceivePostRebalanceFrom1 + expectedAmountToReceivePostRebalanceFrom2; From ccc551a8ceebb6eff621b8ae2406e31e6f18c15f Mon Sep 17 00:00:00 2001 From: Timepunk <45543880+0xTimepunk@users.noreply.github.com> Date: Wed, 30 Oct 2024 14:33:56 +0000 Subject: [PATCH 44/44] fix: balanceDiff --- Makefile | 3 +- .../router-plus/SuperformRouterPlus.t.sol | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 281b05636..26c8f9105 100644 --- a/Makefile +++ b/Makefile @@ -121,8 +121,7 @@ build-sizes: ## Builds the project and shows sizes .PHONY: test-vvv test-vvv: ## Runs tests with verbose output - forge test --match-contract SuperformRouterPlusTest --evm-version cancun - + forge test --match-test test_rebalanceMultiPositions_tokenRefunds_interimDust_allowanceNot0 --evm-version cancun -vvvvv .PHONY: ftest ftest: ## Runs tests with cancun evm version diff --git a/test/unit/router-plus/SuperformRouterPlus.t.sol b/test/unit/router-plus/SuperformRouterPlus.t.sol index ca9ec4106..4c085e773 100644 --- a/test/unit/router-plus/SuperformRouterPlus.t.sol +++ b/test/unit/router-plus/SuperformRouterPlus.t.sol @@ -806,6 +806,56 @@ contract SuperformRouterPlusTest is ProtocolActions { SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); } + function test_rebalanceMultiPositions_tokenRefunds_interimDust() public { + vm.startPrank(deployer); + + _directDeposit(superformId1, 1e18); + _directDeposit(superformId2, 1e6); + + (ISuperformRouterPlus.RebalanceMultiPositionsSyncArgs memory args, uint256 totalAmountToDeposit) = + _buildRebalanceTwoPositionsToOneVaultXChainArgs(); + + SingleVaultSFData memory sfDataRebalanceTo = + abi.decode(_parseCallData(args.rebalanceToCallData), (SingleXChainSingleVaultStateReq)).superformData; + + /// @dev keeper attempting to rug the user by reducing amount in + sfDataRebalanceTo.liqRequest.txData = _buildLiqBridgeTxData( + LiqBridgeTxDataArgs( + 1, + args.interimAsset, + getContract(OP, "DAI"), + getContract(OP, "DAI"), + getContract(SOURCE_CHAIN, "SuperformRouter"), + SOURCE_CHAIN, + OP, + OP, + false, + getContract(OP, "CoreStateRegistry"), + uint256(OP), + totalAmountToDeposit - 1e4, + false, + 0, + 1, + 1, + 1, + address(0) + ), + false + ); + + args.rebalanceToCallData = abi.encodeCall( + IBaseRouter.singleXChainSingleVaultDeposit, SingleXChainSingleVaultStateReq(AMBs, OP, sfDataRebalanceTo) + ); + + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance( + ROUTER_PLUS_SOURCE, superformId1, args.sharesToRedeem[0] + ); + SuperPositions(SUPER_POSITIONS_SOURCE).increaseAllowance( + ROUTER_PLUS_SOURCE, superformId2, args.sharesToRedeem[1] + ); + SuperformRouterPlus(ROUTER_PLUS_SOURCE).rebalanceMultiPositions{ value: 2 ether }(args); + } + function test_rebalanceSinglePosition_singleXChainSingleVaultDepositSelector() public { vm.startPrank(deployer);