@@ -174,7 +174,7 @@ contract FeeForkTest is Test {
174174
175175 vm.startPrank (APP_USER_ALICE);
176176 underlyingERC20.approve (address (aavePerfFeeFacet), depositAmount);
177- console.log ("approved USDC to aave " );
177+ console.log ("approved USDC to the fee contract " );
178178 aavePerfFeeFacet.depositToAave (REAL_USDC, depositAmount);
179179 vm.stopPrank ();
180180 console.log ("deposited to aave " );
@@ -221,4 +221,123 @@ contract FeeForkTest is Test {
221221 address [] memory tokensWithCollectedFees = feeAdminFacet.tokensWithCollectedFees ();
222222 assertEq (tokensWithCollectedFees.length , 0 );
223223 }
224+
225+ function testMultipleDepositAndWithdrawFromAaveWithProfit () public {
226+ // set the performance fee percentage to 5% in basis points
227+ uint256 performanceFeePercentage = 500 ;
228+
229+ // set the performance fee percentage to 5%
230+ vm.startPrank (owner);
231+ assertNotEq (feeAdminFacet.performanceFeePercentage (), performanceFeePercentage);
232+ feeAdminFacet.setPerformanceFeePercentage (performanceFeePercentage);
233+ assertEq (feeAdminFacet.performanceFeePercentage (), performanceFeePercentage);
234+ vm.stopPrank ();
235+
236+ uint256 depositAmount = 50 * 10 ** erc20Decimals;
237+
238+ // mint the USDC to the user
239+ vm.startPrank (USDC_MINTER);
240+ underlyingERC20.mint (APP_USER_ALICE, depositAmount);
241+ vm.stopPrank ();
242+ console.log ("minted USDC to user " );
243+
244+ vm.startPrank (APP_USER_ALICE);
245+ underlyingERC20.approve (address (aavePerfFeeFacet), depositAmount);
246+ console.log ("approved USDC to aave " );
247+ aavePerfFeeFacet.depositToAave (REAL_USDC, depositAmount);
248+ vm.stopPrank ();
249+ console.log ("deposited to aave " );
250+
251+ LibFeeStorage.Deposit memory d = feeViewsFacet.deposits (APP_USER_ALICE, REAL_USDC);
252+
253+ assertEq (d.assetAmount, depositAmount);
254+ console.log ("d.vaultShares " , d.vaultShares);
255+ console.log ("d.vaultProvider " , d.vaultProvider);
256+
257+ // confirm that the fee contract has the aTokens
258+ ERC20 aToken = ERC20 (aavePool.getReserveAToken (REAL_USDC));
259+ uint256 feeContractAaveTokens = aToken.balanceOf (address (aavePerfFeeFacet));
260+ console.log ("feeContractAaveTokens " , feeContractAaveTokens);
261+ // due to aave fees / rounding math, we get back 1 less aToken than we deposited
262+ assertEq (feeContractAaveTokens / 10 ** aToken.decimals (), (depositAmount / 10 ** erc20Decimals) - 1 );
263+
264+ // deposit again
265+ vm.startPrank (USDC_MINTER);
266+ underlyingERC20.mint (APP_USER_ALICE, depositAmount);
267+ vm.stopPrank ();
268+ console.log ("minted USDC to user " );
269+
270+ vm.startPrank (APP_USER_ALICE);
271+ underlyingERC20.approve (address (aavePerfFeeFacet), depositAmount);
272+ console.log ("approved USDC to the fee contract " );
273+ aavePerfFeeFacet.depositToAave (REAL_USDC, depositAmount);
274+ vm.stopPrank ();
275+ console.log ("deposited to aave " );
276+
277+ depositAmount = depositAmount * 2 ;
278+
279+ d = feeViewsFacet.deposits (APP_USER_ALICE, REAL_USDC);
280+
281+ assertEq (d.assetAmount, depositAmount);
282+ console.log ("d.vaultShares " , d.vaultShares);
283+ console.log ("d.vaultProvider " , d.vaultProvider);
284+
285+ // confirm that the fee contract has the aTokens
286+ feeContractAaveTokens = aToken.balanceOf (address (aavePerfFeeFacet));
287+ console.log ("feeContractAaveTokens " , feeContractAaveTokens);
288+ // due to aave fees / rounding math, we get back 1 less aToken than we deposited
289+ assertEq (feeContractAaveTokens / 10 ** aToken.decimals (), (depositAmount / 10 ** erc20Decimals) - 1 );
290+
291+ // advance timestamp to 1 week from now to accrue interest, to simulate profit
292+ // aave is rebasing so this should just be a bigger of aTokens after 1 week
293+ vm.warp (block .timestamp + 1 weeks);
294+ uint256 expectedTotalWithdrawl = aToken.balanceOf (address (aavePerfFeeFacet));
295+ console.log ("expectedTotalWithdrawl - aka the aTokens in the fee contract after 1 week " , expectedTotalWithdrawl);
296+ assertGt (expectedTotalWithdrawl, feeContractAaveTokens);
297+
298+ // now, do the withdrawal
299+ vm.startPrank (APP_USER_ALICE);
300+ aavePerfFeeFacet.withdrawFromAave (REAL_USDC);
301+ vm.stopPrank ();
302+
303+ // confirm the deposit is zeroed out
304+ d = feeViewsFacet.deposits (APP_USER_ALICE, REAL_USDC);
305+
306+ assertEq (d.assetAmount, 0 );
307+ assertEq (d.vaultShares, 0 );
308+ assertEq (d.vaultProvider, 0 );
309+
310+ // confirm the profit went to the fee contract, and some went to the user
311+ uint256 userBalance = underlyingERC20.balanceOf (APP_USER_ALICE);
312+ uint256 feeContractBalance = underlyingERC20.balanceOf (address (aavePerfFeeFacet));
313+
314+ uint256 expectedTotalProfit = expectedTotalWithdrawl - depositAmount;
315+ uint256 expectedUserProfit = expectedTotalProfit - (expectedTotalProfit * performanceFeePercentage / 10000 );
316+ uint256 expectedFeeContractProfit = expectedTotalProfit * performanceFeePercentage / 10000 ;
317+ console.log ("expectedTotalProfit " , expectedTotalProfit);
318+ console.log ("expectedUserProfit " , expectedUserProfit);
319+ console.log ("expectedFeeContractProfit " , expectedFeeContractProfit);
320+ console.log ("userProfit " , userBalance);
321+ console.log ("feeContractProfit " , feeContractBalance);
322+
323+ assertEq (userBalance, depositAmount + expectedUserProfit);
324+ assertEq (feeContractBalance, expectedFeeContractProfit);
325+
326+ // test that the MockERC20 is in the set of tokens that have collected fees
327+ address [] memory tokensWithCollectedFees = feeAdminFacet.tokensWithCollectedFees ();
328+ assertEq (tokensWithCollectedFees.length , 1 );
329+ assertEq (tokensWithCollectedFees[0 ], address (underlyingERC20));
330+
331+ // test withdrawal of profit from the fee contract as owner
332+ vm.startPrank (owner);
333+ feeAdminFacet.withdrawTokens (address (underlyingERC20));
334+ vm.stopPrank ();
335+
336+ // confirm the profit went to the owner
337+ assertEq (underlyingERC20.balanceOf (owner), expectedFeeContractProfit);
338+
339+ // confirm that the token is no longer in the set of tokens that have collected fees
340+ tokensWithCollectedFees = feeAdminFacet.tokensWithCollectedFees ();
341+ assertEq (tokensWithCollectedFees.length , 0 );
342+ }
224343}
0 commit comments