Skip to content

Commit

Permalink
feat: remove all user funds after invariants.
Browse files Browse the repository at this point in the history
  • Loading branch information
clement-ux committed Oct 15, 2024
1 parent 5e685b1 commit 5df7718
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 26 deletions.
43 changes: 22 additions & 21 deletions test/invariants/BaseInvariants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ abstract contract Invariant_Base_Test_ is Invariant_Shared_Test_ {
* Invariant C: previewRedeem(∑shares) == totalAssets
* Invariant D: previewRedeem(shares) == (, uint256 assets) = previewRedeem(shares) Not really invariant, but tested on handler
* Invariant E: previewDeposit(amount) == uint256 shares = previewDeposit(amount) Not really invariant, but tested on handler
* Invariant L: ∀ user, weth balances + previewRedeem(user shares) >= initialWETHBalance. // i.e. shares are up only.
* Withdraw Queue:
* Invariant F: nextWithdrawalIndex == requestRedeem call count
Expand All @@ -70,6 +69,11 @@ abstract contract Invariant_Base_Test_ is Invariant_Shared_Test_ {
* Invariant B: address(arm).balance == 0
* Invariant C: All slot allow for gap are empty
* After invariants:
* All user can withdraw their funds
* Log stats
*/

//////////////////////////////////////////////////////
Expand Down Expand Up @@ -161,21 +165,6 @@ abstract contract Invariant_Base_Test_ is Invariant_Shared_Test_ {
assertEq(weth.balanceOf(feeCollector), ownerHandler.sum_of_fees(), "lpHandler.invariant_M");
}

function assert_lp_invariant_L(uint256 initialUserWETHBalance) public {
// 1. Finalize all claims on Lido
llmHandler.finalizeAllClaims();
// 2. Swap all stETH to WETH
_sweepAllStETH();
// 3. Finalize all claim redeem on ARM.
lpHandler.finalizeAllClaims();
// 4. Check that all shares values are up only -> WETH balance + previewRedeem(shares) >= MAX_WETH_PER_USERS
for (uint256 i; i < lps.length; i++) {
address user = lps[i];
uint256 previewRedeem = lidoARM.previewRedeem(lidoARM.balanceOf(user));
assertGe(weth.balanceOf(user) + previewRedeem + 1, initialUserWETHBalance, "lpHandler.invariant_L");
}
}

//////////////////////////////////////////////////////
/// --- LIDO LIQUIDITY MANAGER ASSERTIONS
//////////////////////////////////////////////////////
Expand Down Expand Up @@ -228,6 +217,23 @@ abstract contract Invariant_Base_Test_ is Invariant_Shared_Test_ {
assertApproxEqAbs(steth.balanceOf(address(lidoARM)), 0, 1, "SwepAllStETH");
}

/// @notice Empties the ARM
/// @dev Finalize all claims on lido, swap all stETH to WETH, finalize all
/// claim redeem on ARM and withdraw all user funds.
function emptiesARM() internal {
// 1. Finalize all claims on Lido
llmHandler.finalizeAllClaims();

// 2. Swap all stETH to WETH
_sweepAllStETH();

// 3. Finalize all claim redeem on ARM.
lpHandler.finalizeAllClaims();

// 4. Withdraw all user funds
lpHandler.withdrawAllUserFunds();
}

/// @notice Absolute difference between two numbers
function absDiff(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a - b : b - a;
Expand All @@ -237,11 +243,6 @@ abstract contract Invariant_Base_Test_ is Invariant_Shared_Test_ {
value = uint256(vm.load(address(lidoARM), bytes32(slotNumber)));
}

modifier logStat(bool display) {
_;
if (display) logStats();
}

function logStats() public view {
// Don't trace this function as it's only for logging data.
vm.pauseTracing();
Expand Down
13 changes: 8 additions & 5 deletions test/invariants/BasicInvariants.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ contract Invariant_Basic_Test_ is Invariant_Base_Test_ {
uint256 private constant MAX_SELL_T1 = 1.02 * 1e36; // We could have use type(uint256).max, but this is non-sense
uint256 private constant MAX_WETH_PER_USERS = 10_000 ether; // 10M
uint256 private constant MAX_STETH_PER_USERS = 10_000 ether; // 10M, actual total supply
bool private constant LOG_STATS = true; // Reduce speed but increase readability when debugging invariants.

//////////////////////////////////////////////////////
/// --- SETUP
Expand Down Expand Up @@ -110,7 +109,7 @@ contract Invariant_Basic_Test_ is Invariant_Base_Test_ {
//////////////////////////////////////////////////////
/// --- INVARIANTS
//////////////////////////////////////////////////////
function invariant_lp() external logStat(LOG_STATS) {
function invariant_lp() external view {
assert_lp_invariant_A();
assert_lp_invariant_B();
assert_lp_invariant_C();
Expand All @@ -122,18 +121,22 @@ contract Invariant_Basic_Test_ is Invariant_Base_Test_ {
assert_lp_invariant_I();
assert_lp_invariant_J();
assert_lp_invariant_K();
assert_lp_invariant_L(MAX_WETH_PER_USERS);
assert_lp_invariant_M();
}

function invariant_swap() external view logStat(LOG_STATS) {
function invariant_swap() external view {
assert_swap_invariant_A();
assert_swap_invariant_B();
}

function invariant_llm() external view logStat(LOG_STATS) {
function invariant_llm() external view {
assert_llm_invariant_A();
assert_llm_invariant_B();
assert_llm_invariant_C();
}

function afterInvariant() external {
logStats();
emptiesARM();
}
}
23 changes: 23 additions & 0 deletions test/invariants/handlers/LpHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,29 @@ contract LpHandler is BaseHandler {
rewind(arm.claimDelay());
}

/// @notice Withdraw all user funds
/// @dev This function assumes that all pending request on lido have been finalized,
/// all stETH have been swapped to WETH and all claim redeem requests have been finalized.
function withdrawAllUserFunds() external {
for (uint256 i; i < lps.length; i++) {
address user = lps[i];
vm.startPrank(user);

// Request Claim
(uint256 requestId,) = arm.requestRedeem(arm.balanceOf(user));

// Timejump to request deadline
skip(arm.claimDelay());

// Claim request
arm.claimRedeem(requestId);

// Jump back to current time, to avoid issues with other tests
rewind(arm.claimDelay());
vm.stopPrank();
}
}

/// @notice Get all requests for a user
function getRequests(address user) external view returns (uint256[] memory) {
return requests[user];
Expand Down

0 comments on commit 5df7718

Please sign in to comment.