From 43c0d39f351ec2ec354d800343c62d7e6b6541e6 Mon Sep 17 00:00:00 2001 From: danoctavian Date: Wed, 6 Mar 2024 07:36:05 +0200 Subject: [PATCH 1/2] remove pointless TODOs --- src/ynETH.sol | 2 -- test/foundry/ActorAddresses.sol | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ynETH.sol b/src/ynETH.sol index a0482b22d..171a3d96a 100644 --- a/src/ynETH.sol +++ b/src/ynETH.sol @@ -114,8 +114,6 @@ contract ynETH is IynETH, ynBase, IStakingEvents { emit Deposit(msg.sender, receiver, assets, shares); } - // TODO: solve for deposit and mint to adjust to new variables - /// @notice Converts from ynETH to ETH using the current exchange rate. /// The exchange rate is given by the total supply of ynETH and total ETH controlled by the protocol. function _convertToShares(uint256 ethAmount, Math.Rounding rounding) internal view returns (uint256) { diff --git a/test/foundry/ActorAddresses.sol b/test/foundry/ActorAddresses.sol index 9c6e049fd..c32c1aa5d 100644 --- a/test/foundry/ActorAddresses.sol +++ b/test/foundry/ActorAddresses.sol @@ -33,7 +33,7 @@ contract ActorAddresses { PAUSE_ADMIN: 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f, LSD_RESTAKING_MANAGER: 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720, STAKING_NODE_CREATOR: 0xBcd4042DE499D14e55001CcbB24a551F3b954096, - ORACLE_MANAGER: 0x71bE63f3384f5fb98995898A86B02Fb2426c5788 // TODO: put the next addres here + ORACLE_MANAGER: 0x71bE63f3384f5fb98995898A86B02Fb2426c5788 }); actors[5] = Actors({ @@ -48,7 +48,7 @@ contract ActorAddresses { PAUSE_ADMIN: 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f, LSD_RESTAKING_MANAGER: 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720, STAKING_NODE_CREATOR: 0xBcd4042DE499D14e55001CcbB24a551F3b954096, - ORACLE_MANAGER: 0x71bE63f3384f5fb98995898A86B02Fb2426c5788 // TODO: put the next addres here + ORACLE_MANAGER: 0x71bE63f3384f5fb98995898A86B02Fb2426c5788 }); } From e873f3412be84fbf562d0bbfb9a4243038139b53 Mon Sep 17 00:00:00 2001 From: danoctavian Date: Wed, 6 Mar 2024 08:36:18 +0200 Subject: [PATCH 2/2] add setFeesBasisPoints --- src/RewardsDistributor.sol | 13 +++++++++++++ test/foundry/integration/RewardsDistributor.t.sol | 15 +++++++++++++++ test/foundry/integration/StakingNode.t.sol | 13 ++++++++++++- test/foundry/integration/ynLSD.t.sol | 8 +++++--- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/RewardsDistributor.sol b/src/RewardsDistributor.sol index 1eb5a7b0c..f35849495 100644 --- a/src/RewardsDistributor.sol +++ b/src/RewardsDistributor.sol @@ -11,6 +11,7 @@ import {IynETH} from "./interfaces/IynETH.sol"; interface RewardsDistributorEvents { event FeesCollected(uint256 amount); event FeeReceiverSet(address ewReceiver); + event FeesBasisPointsSet(uint256 feeBasisPoints); } @@ -25,6 +26,7 @@ contract RewardsDistributor is Initializable, AccessControlUpgradeable, RewardsD error Paused(); error ZeroAddress(); error FeeSendFailed(); + error InvalidBasisPoints(); //-------------------------------------------------------------------------------------- //---------------------------------- CONSTANTS --------------------------------------- @@ -140,6 +142,17 @@ contract RewardsDistributor is Initializable, AccessControlUpgradeable, RewardsD emit FeeReceiverSet(newReceiver); } + /// @notice Sets the fees basis points for the protocol. + /// @param newFeesBasisPoints The new fees basis points. + function setFeesBasisPoints(uint16 newFeesBasisPoints) + external + onlyRole(DEFAULT_ADMIN_ROLE) + { + if (newFeesBasisPoints > _BASIS_POINTS_DENOMINATOR) revert InvalidBasisPoints(); + feesBasisPoints = newFeesBasisPoints; + emit FeesBasisPointsSet(newFeesBasisPoints); + } + modifier assertBalanceUnchanged() { uint256 before = address(this).balance; _; diff --git a/test/foundry/integration/RewardsDistributor.t.sol b/test/foundry/integration/RewardsDistributor.t.sol index 13b6f398b..98c7f67ce 100644 --- a/test/foundry/integration/RewardsDistributor.t.sol +++ b/test/foundry/integration/RewardsDistributor.t.sol @@ -46,4 +46,19 @@ contract RewardsDistributorTest is IntegrationBaseTest { rewardsDistributor.processRewards(); vm.stopPrank(); } + + function testSetFeeBasisPoints() public { + uint16 newFeeBasisPoints = 500; // 5% + vm.prank(actors.ADMIN); + rewardsDistributor.setFeesBasisPoints(newFeeBasisPoints); + assertEq(rewardsDistributor.feesBasisPoints(), newFeeBasisPoints); + } + + function testFailSetFeeBasisPointsExceedsLimit() public { + + uint16 newFeeBasisPoints = 15000; // 150%, exceeds 100% + vm.prank(actors.ADMIN); + vm.expectRevert(abi.encodeWithSelector(RewardsDistributor.InvalidBasisPoints.selector, newFeeBasisPoints)); + rewardsDistributor.setFeesBasisPoints(newFeeBasisPoints); + } } \ No newline at end of file diff --git a/test/foundry/integration/StakingNode.t.sol b/test/foundry/integration/StakingNode.t.sol index 955b7c405..5a09bcaed 100644 --- a/test/foundry/integration/StakingNode.t.sol +++ b/test/foundry/integration/StakingNode.t.sol @@ -75,7 +75,9 @@ contract StakingNodeEigenPod is StakingNodeTestBase { function testCreateNodeAndVerifyPodStateIsValid() public { - (IStakingNode stakingNodeInstance, IEigenPod eigenPodInstance) = setupStakingNode(32 ether); + uint depositAmount = 32 ether; + + (IStakingNode stakingNodeInstance, IEigenPod eigenPodInstance) = setupStakingNode(depositAmount); // Collapsed variable declarations into direct usage within assertions and conditions @@ -108,6 +110,15 @@ contract StakingNodeEigenPod is StakingNodeTestBase { uint256 rewardsAmount = balanceAfterClaim - balanceBeforeClaim; assertEq(rewardsAmount, rewardsSweeped, "Rewards amount does not match expected value"); + + rewardsDistributor.processRewards(); + + uint256 fee = uint256(rewardsDistributor.feesBasisPoints()); + uint finalRewardsReceived = rewardsAmount - (rewardsAmount * fee / 10000); + + // Assert total assets after claiming delayed withdrawals + uint256 totalAssets = yneth.totalAssets(); + assertEq(totalAssets, finalRewardsReceived + depositAmount, "Total assets after claiming delayed withdrawals do not match expected value"); } } diff --git a/test/foundry/integration/ynLSD.t.sol b/test/foundry/integration/ynLSD.t.sol index 604c9c880..6acc59677 100644 --- a/test/foundry/integration/ynLSD.t.sol +++ b/test/foundry/integration/ynLSD.t.sol @@ -15,6 +15,8 @@ import {TestLSDStakingNodeV2} from "../mocks/TestLSDStakingNodeV2.sol"; import {TestYnLSDV2} from "../mocks/TestYnLSDV2.sol"; import {ynBase} from "../../../src/ynBase.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import "forge-std/console.sol"; + contract ynLSDAssetTest is IntegrationBaseTest { @@ -175,6 +177,7 @@ contract ynLSDAssetTest is IntegrationBaseTest { emit log_uint(balance); assertEq(balance, amount, "Amount not received"); asset.approve(address(ynlsd), amount); + ynlsd.deposit(asset, amount, address(this)); { IERC20[] memory assets = new IERC20[](1); @@ -184,8 +187,7 @@ contract ynLSDAssetTest is IntegrationBaseTest { vm.prank(actors.LSD_RESTAKING_MANAGER); - // TODO: Come back to this - // lsdStakingNode.depositAssetsToEigenlayer(assets, amounts); + lsdStakingNode.depositAssetsToEigenlayer(assets, amounts); } uint256 totalAssetsAfterDeposit = ynlsd.totalAssets(); @@ -194,7 +196,7 @@ contract ynLSDAssetTest is IntegrationBaseTest { IStrategy strategy = ynlsd.strategies(IERC20(chainAddresses.lsd.STETH_ADDRESS)); uint256 balanceInStrategyForNode = strategy.userUnderlyingView((address(lsdStakingNode))); - + uint256 expectedBalance = balanceInStrategyForNode * oraclePrice / 1e18; // Assert that totalAssets reflects the deposit