Skip to content

Commit

Permalink
test: extra stress test
Browse files Browse the repository at this point in the history
  • Loading branch information
0xTimepunk committed Nov 25, 2024
1 parent 3b64800 commit 8ae5a8f
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ update:; forge update
# Build & test
build :; FOUNDRY_PROFILE=production forge build
build-sizes :; FOUNDRY_PROFILE=production forge build --sizes
test-vvv :; forge test --match-test test_superVault_assertSuperPositions_splitAccordingToWeights --evm-version cancun -vvv
test-vvv :; forge test --match-test test_superVault_multiUser_stress --evm-version cancun -vv
ftest :; forge test --evm-version cancun
coverage :; forge coverage --evm-version cancun --report lcov
clean :; forge clean
Expand Down
3 changes: 0 additions & 3 deletions src/SuperVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { SafeERC20 } from "openzeppelin-contracts/contracts/token/ERC20/utils/Sa
import { ERC20 } from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import { IERC165 } from "openzeppelin/contracts/utils/introspection/IERC165.sol";
import { IERC4626 } from "openzeppelin/contracts/interfaces/IERC4626.sol";
import { SingleDirectMultiVaultStateReq, MultiVaultSFData, LiqRequest } from "superform-core/src/types/DataTypes.sol";
import { ISuperPositions } from "superform-core/src/interfaces/ISuperPositions.sol";
import { DataLib } from "superform-core/src/libraries/DataLib.sol";
Expand All @@ -18,9 +17,7 @@ import { ISuperformRouterPlus } from "superform-core/src/interfaces/ISuperformRo
import { ISuperRegistry } from "superform-core/src/interfaces/ISuperRegistry.sol";
import { ISuperVault, IERC1155Receiver } from "./interfaces/ISuperVault.sol";
import { ISuperformFactory } from "superform-core/src/interfaces/ISuperformFactory.sol";
import { IERC5115To4626Wrapper } from "superform-core/src/forms/interfaces/IERC5115To4626Wrapper.sol";
import { BaseStrategy } from "tokenized-strategy/BaseStrategy.sol";
import { ITokenizedStrategy } from "tokenized-strategy/interfaces/ITokenizedStrategy.sol";
import { ISuperformFactoryMinimal } from "./interfaces/ISuperformFactoryMinimal.sol";

/// @title SuperVault
Expand Down
172 changes: 153 additions & 19 deletions test/SuperVault.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -376,11 +376,11 @@ contract SuperVaultTest is ProtocolActions {

uint256 amount = 500e6;
// Perform a direct deposit to the SuperVault
_directDeposit(SUPER_VAULT_ID1, amount);
_directDeposit(deployer, SUPER_VAULT_ID1, amount);

_assertSuperPositionsSplitAccordingToWeights(ETH);

_directWithdraw(SUPER_VAULT_ID1, false);
_directWithdraw(deployer, SUPER_VAULT_ID1, false);

_assertUnderlyingBalanceAfterFullWithdraw(ETH);

Expand Down Expand Up @@ -592,7 +592,7 @@ contract SuperVaultTest is ProtocolActions {

uint256 amount = 10_000e6;
// Perform a direct deposit to the SuperVault
_directDeposit(SUPER_VAULT_ID1, amount);
_directDeposit(deployer, SUPER_VAULT_ID1, amount);

_assertSuperPositionsSplitAccordingToWeights(ETH);

Expand Down Expand Up @@ -637,7 +637,7 @@ contract SuperVaultTest is ProtocolActions {

uint256 amount = 10_000e6;
// Perform a direct deposit to the SuperVault
_directDeposit(SUPER_VAULT_ID1, amount);
_directDeposit(deployer, SUPER_VAULT_ID1, amount);

_assertSuperPositionsSplitAccordingToWeights(ETH);

Expand Down Expand Up @@ -679,7 +679,7 @@ contract SuperVaultTest is ProtocolActions {

uint256 amount = 10_000e6;
// Perform a direct deposit to the SuperVault
_directDeposit(SUPER_VAULT_ID1, amount);
_directDeposit(deployer, SUPER_VAULT_ID1, amount);

_assertSuperPositionsSplitAccordingToWeights(ETH);

Expand Down Expand Up @@ -713,7 +713,7 @@ contract SuperVaultTest is ProtocolActions {
console.log("----withdrawing full balance----");

// Withdraw full balance
_directWithdraw(SUPER_VAULT_ID1, false);
_directWithdraw(deployer, SUPER_VAULT_ID1, false);

_assertUnderlyingBalanceAfterFullWithdraw(ETH);
}
Expand All @@ -727,7 +727,7 @@ contract SuperVaultTest is ProtocolActions {

// Initial deposit
uint256 amount = 50_000e6; // Larger initial deposit
_directDeposit(SUPER_VAULT_ID1, amount);
_directDeposit(deployer, SUPER_VAULT_ID1, amount);
_assertSuperPositionsSplitAccordingToWeights(ETH);

for (uint256 i = 0; i < allSuperformIds.length; i++) {
Expand Down Expand Up @@ -760,7 +760,7 @@ contract SuperVaultTest is ProtocolActions {

console.log("----additional deposit----");
// Additional deposit
_directDeposit(SUPER_VAULT_ID1, amount);
_directDeposit(deployer, SUPER_VAULT_ID1, amount);

// Second rebalance: Split between index 0 and 4
finalIndexes = new uint256[](2);
Expand All @@ -784,7 +784,7 @@ contract SuperVaultTest is ProtocolActions {
}
console.log("----partial withdraw----");
// Partial withdraw
_directWithdraw(SUPER_VAULT_ID1, true);
_directWithdraw(deployer, SUPER_VAULT_ID1, true);

// Third rebalance: Move everything back to index 4
finalIndexes = new uint256[](1);
Expand All @@ -805,12 +805,146 @@ contract SuperVaultTest is ProtocolActions {
}
// Final withdrawal
console.log("----withdrawing remaining balance----");
_directWithdraw(SUPER_VAULT_ID1, false);
_directWithdraw(deployer, SUPER_VAULT_ID1, false);
_assertUnderlyingBalanceAfterFullWithdraw(ETH);

vm.stopPrank();
}

function test_superVault_multiUser_stress() public {
vm.startPrank(deployer);
SOURCE_CHAIN = ETH;

(address superFormSuperVault,,) = SUPER_VAULT_ID1.getSuperform();
address superVaultAddress = IBaseForm(superFormSuperVault).getVaultAddress();
address usdcToken = getContract(ETH, "USDC");

// Setup 5 users with different deposit amounts
address[] memory users_ = new address[](5);
uint256[] memory depositAmounts = new uint256[](5);
for (uint256 i = 0; i < 5; i++) {
users_[i] = address(uint160(0x1000 + i));
depositAmounts[i] = (i + 1) * 10_000e6; // 10k, 20k, 30k, 40k, 50k USDC
vm.deal(users_[i], 10 ether);
deal(usdcToken, users_[i], depositAmounts[i]);
}

// First wave of deposits (users 0, 1, 2)
for (uint256 i = 0; i < 3; i++) {
vm.startPrank(users_[i]);
_directDeposit(users_[i], SUPER_VAULT_ID1, depositAmounts[i]);
vm.stopPrank();
}

_assertSuperPositionsSplitAccordingToWeights(ETH);
console.log("----Initial deposits completed----");
_logSuperPositionBalances(superVaultAddress);

// First rebalance: Move majority to indexes 0 and 1
uint256[] memory finalIndexes = new uint256[](2);
finalIndexes[0] = 0;
finalIndexes[1] = 1;
uint256[] memory finalWeightsTargets = new uint256[](2);
finalWeightsTargets[0] = 6000; // 60%
finalWeightsTargets[1] = 4000; // 40%
uint256[] memory indexesRebalanceFrom = new uint256[](1);
indexesRebalanceFrom[0] = 2;

console.log("----First rebalance: 60% index 0, 40% index 1----");
vm.startPrank(deployer);
_performRebalance(finalIndexes, finalWeightsTargets, indexesRebalanceFrom);
_assertWeightsWithinTolerance(finalIndexes, finalWeightsTargets);
vm.stopPrank();
_logSuperPositionBalances(superVaultAddress);

console.log("----Second wave of deposits (users 3, 4) and first withdrawal (user 0)----");
vm.startPrank(users_[0]);
_directWithdraw(users_[0], SUPER_VAULT_ID1, true); // Partial withdrawal
vm.stopPrank();

for (uint256 i = 3; i < 5; i++) {
vm.startPrank(users_[i]);
_directDeposit(users_[i], SUPER_VAULT_ID1, depositAmounts[i]);
vm.stopPrank();
}

console.log("----After more deposits and first withdrawal----");
_logSuperPositionBalances(superVaultAddress);

// Second rebalance: Redistribute across all three indexes
finalIndexes = new uint256[](3);
finalIndexes[0] = 0;
finalIndexes[1] = 1;
finalIndexes[2] = 4;
finalWeightsTargets = new uint256[](3);
finalWeightsTargets[0] = 4000; // 40%
finalWeightsTargets[1] = 3000; // 30%
finalWeightsTargets[2] = 3000; // 30%
indexesRebalanceFrom = new uint256[](2);
indexesRebalanceFrom[0] = 0;
indexesRebalanceFrom[1] = 1;

console.log("----Second rebalance: 40/30/30 split----");
vm.startPrank(deployer);
_performRebalance(finalIndexes, finalWeightsTargets, indexesRebalanceFrom);
_assertWeightsWithinTolerance(finalIndexes, finalWeightsTargets);
vm.stopPrank();
_logSuperPositionBalances(superVaultAddress);

console.log("----Final wave of mixed actions----");
vm.startPrank(users_[1]);
_directWithdraw(users_[1], SUPER_VAULT_ID1, false); // Full withdrawal
vm.stopPrank();

vm.startPrank(users_[2]);
_directWithdraw(users_[2], SUPER_VAULT_ID1, true); // Partial withdrawal
vm.stopPrank();

vm.startPrank(users_[3]);
deal(usdcToken, users_[3], depositAmounts[3]); // Give more USDC
_directDeposit(users_[3], SUPER_VAULT_ID1, depositAmounts[3]); // Additional deposit
vm.stopPrank();

console.log("----After final wave of actions----");
_logSuperPositionBalances(superVaultAddress);

// Final withdrawals
for (uint256 i = 0; i < 5; i++) {
vm.startPrank(users_[i]);
uint256 spBalance = SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(users_[i], SUPER_VAULT_ID1);
if (spBalance > 0) {
_directWithdraw(users_[i], SUPER_VAULT_ID1, false);
}
vm.stopPrank();
}

console.log("----After all withdrawals----");
_logSuperPositionBalances(superVaultAddress);
_assertUnderlyingBalanceAfterFullWithdraw(ETH);

vm.stopPrank();
}

function _logSuperPositionBalances(address superVaultAddress) internal view {
for (uint256 i = 0; i < allSuperformIds.length; i++) {
uint256 spBalanceInSuperVault =
SuperPositions(SUPER_POSITIONS_SOURCE).balanceOf(superVaultAddress, allSuperformIds[i]);
(address superform,,) = allSuperformIds[i].getSuperform();
uint256 underlyingBalance = IBaseForm(superform).previewRedeemFrom(spBalanceInSuperVault);
console.log(
string.concat(
"SuperPosition ",
Strings.toString(i),
" balance: ",
Strings.toString(spBalanceInSuperVault),
" (",
Strings.toString(underlyingBalance),
" underlying)"
)
);
}
}

function test_superVault_rebalance_emptyAmountsRebalanceFrom() public {
uint256[] memory superformIdsRebalanceFrom = new uint256[](2);
superformIdsRebalanceFrom[0] = underlyingSuperformIds[0];
Expand Down Expand Up @@ -922,7 +1056,7 @@ contract SuperVaultTest is ProtocolActions {

// Perform direct deposit for the current user
vm.startPrank(depositUsers[i]);
_directDeposit(SUPER_VAULT_ID1, depositAmount);
_directDeposit(depositUsers[i], SUPER_VAULT_ID1, depositAmount);
vm.stopPrank();

// Warp 1 day
Expand Down Expand Up @@ -1001,7 +1135,7 @@ contract SuperVaultTest is ProtocolActions {
// Perform a direct deposit to the SuperVault
(address superform,,) = SUPER_VAULT_ID1.getSuperform();
deal(IBaseForm(superform).getVaultAsset(), deployer, amount);
_directDeposit(SUPER_VAULT_ID1, amount);
_directDeposit(deployer, SUPER_VAULT_ID1, amount);

_assertSuperPositionsSplitAccordingToWeights(ETH);

Expand Down Expand Up @@ -1048,7 +1182,7 @@ contract SuperVaultTest is ProtocolActions {
// INTERNAL HELPERS //
//////////////////////////////////////////////////////////////

function _directDeposit(uint256 superformId, uint256 amount) internal {
function _directDeposit(address user, uint256 superformId, uint256 amount) internal {
vm.selectFork(FORKS[SOURCE_CHAIN]);
(address superform,,) = superformId.getSuperform();

Expand All @@ -1061,8 +1195,8 @@ contract SuperVaultTest is ProtocolActions {
"",
false,
false,
deployer,
deployer,
user,
user,
""
);

Expand All @@ -1077,11 +1211,11 @@ contract SuperVaultTest is ProtocolActions {
}(req);
}

function _directWithdraw(uint256 superformId, bool partialWithdraw) internal {
function _directWithdraw(address user, uint256 superformId, bool partialWithdraw) internal {
vm.selectFork(FORKS[SOURCE_CHAIN]);
(address superform,,) = superformId.getSuperform();
address superPositions = getContract(SOURCE_CHAIN, "SuperPositions");
uint256 amountToWithdraw = SuperPositions(superPositions).balanceOf(deployer, superformId);
uint256 amountToWithdraw = SuperPositions(superPositions).balanceOf(user, superformId);

if (partialWithdraw) {
amountToWithdraw = amountToWithdraw / 2;
Expand All @@ -1096,8 +1230,8 @@ contract SuperVaultTest is ProtocolActions {
"",
false,
false,
deployer,
deployer,
user,
user,
""
);

Expand Down

0 comments on commit 8ae5a8f

Please sign in to comment.